|
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.
|