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:
parent
dd994c20bc
commit
21da64cca7
@ -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
|
||||
{
|
||||
|
@ -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))
|
||||
@ -3216,12 +3217,13 @@ static void release_blobs(thread_db* tdbb, jrd_req* request)
|
||||
/* Release blobs bound to this request */
|
||||
|
||||
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();
|
||||
|
||||
|
@ -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())
|
||||
if (!transaction->tra_outer)
|
||||
{
|
||||
if (transaction->tra_blobs->getFirst())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
BlobIndex *current = &transaction->tra_blobs.current();
|
||||
BlobIndex *current = &transaction->tra_blobs->current();
|
||||
if (current->bli_materialized) {
|
||||
if (!transaction->tra_blobs.getNext())
|
||||
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))
|
||||
if (!transaction->tra_blobs->locate(Firebird::locGreat, temp_id))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,8 +1185,9 @@ 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;
|
||||
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);
|
||||
|
@ -94,18 +94,28 @@ 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()
|
||||
{
|
||||
if (!tra_outer)
|
||||
delete tra_temp_space;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user