From: <di...@us...> - 2011-12-01 09:25:08
|
Revision: 53654 http://firebird.svn.sourceforge.net/firebird/?rev=53654&view=rev Author: dimitr Date: 2011-12-01 09:24:59 +0000 (Thu, 01 Dec 2011) Log Message: ----------- Attempted to fix CORE-3490: Concurrency problem when using named cursors. The solution may look sub-optimal but it doesn't seem to affect the performance. Modified Paths: -------------- firebird/trunk/src/jrd/vio.cpp Modified: firebird/trunk/src/jrd/vio.cpp =================================================================== --- firebird/trunk/src/jrd/vio.cpp 2011-12-01 09:23:53 UTC (rev 53653) +++ firebird/trunk/src/jrd/vio.cpp 2011-12-01 09:24:59 UTC (rev 53654) @@ -119,6 +119,7 @@ static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction, record_param* rpb); +static void invalidate_cursor_records(jrd_tra*, record_param*); static void list_staying(thread_db*, record_param*, RecordStack&); static void notify_garbage_collector(thread_db*, record_param*, SLONG = -1); static Record* realloc_record(Record*& record, USHORT fmt_length); @@ -1608,6 +1609,11 @@ } } + // We're about to erase the record. Post a refetch request + // to all the active cursors positioned at this record. + + invalidate_cursor_records(transaction, rpb); + // If the page can be updated simply, we can skip the remaining crud record_param temp; @@ -2582,6 +2588,11 @@ } } + // We're about to modify the record. Post a refetch request + // to all the active cursors positioned at this record. + + invalidate_cursor_records(transaction, org_rpb); + // hvlad: prepare_update() take EX lock on data page. Subsequent call of // IDX_modify_flag_uk_modified() will read database - if relation's partners // list has not been scanned yet. It could lead to single thread deadlock @@ -4563,6 +4574,43 @@ } +static void invalidate_cursor_records(jrd_tra* transaction, record_param* mod_rpb) +{ +/************************************** + * + * i n v a l i d a t e _ c u r s o r _ r e c o r d s + * + ************************************** + * + * Functional description + * Post a refetch request to the records currently fetched + * by active cursors of our transaction, because those records + * have just been updated or deleted. + * + **************************************/ + fb_assert(mod_rpb && mod_rpb->rpb_relation); + + for (jrd_req* request = transaction->tra_requests; request; request = request->req_tra_next) + { + if (request->req_flags & req_active) + { + for (size_t i = 0; i < request->req_count; i++) + { + record_param* const org_rpb = &request->req_rpb[i]; + + if (org_rpb != mod_rpb && + org_rpb->rpb_relation && org_rpb->rpb_number.isValid() && + org_rpb->rpb_relation->rel_id == mod_rpb->rpb_relation->rel_id && + org_rpb->rpb_number == mod_rpb->rpb_number) + { + org_rpb->rpb_stream_flags |= RPB_s_refetch; + } + } + } + } +} + + static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& staying) { /************************************** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |