List:Commits« Previous MessageNext Message »
From:vvaintroub Date:April 16 2008 4:15pm
Subject:bk commit into 6.0 tree (vvaintroub:1.2642) BUG#35322
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of vvaintroub.  When vvaintroub does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-04-16 14:14:49+02:00, vvaintroub@wva. +3 -0
  Bug#35322 : Duplicate entries in unique index.
  Make unique-check and insert/update atomic 
  (exclusive lock on index level)

  storage/falcon/Index.h@stripped, 2008-04-16 14:14:47+02:00, vvaintroub@wva. +1 -0
    Bug#35322 : Duplicate entries in unique index.
    Make unique-check and insert/update atomic

  storage/falcon/Table.cpp@stripped, 2008-04-16 14:14:47+02:00, vvaintroub@wva. +74 -74
    Bug#35322 : Duplicate entries in unique index.
    Make unique-check and insert/update atomic

  storage/falcon/Table.h@stripped, 2008-04-16 14:14:48+02:00, vvaintroub@wva. +4 -2
    Bug#35322 : Duplicate entries in unique index.
    Make check for uniqueness and insert atomic

diff -Nrup a/storage/falcon/Index.h b/storage/falcon/Index.h
--- a/storage/falcon/Index.h	2007-10-11 14:57:40 +02:00
+++ b/storage/falcon/Index.h	2008-04-16 14:14:47 +02:00
@@ -152,6 +152,7 @@ public:
 	int			DIHashTableCounts;
 	int			DIHashTableSlotsUsed;
 	SyncObject	syncDIHash;
+	SyncObject	syncUnique;
 };
 
 #endif // !defined(AFX_INDEX_H__02AD6A44_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/Table.cpp b/storage/falcon/Table.cpp
--- a/storage/falcon/Table.cpp	2008-04-11 19:34:16 +02:00
+++ b/storage/falcon/Table.cpp	2008-04-16 14:14:47 +02:00
@@ -84,6 +84,7 @@ static const char *relatedTables [] = {
 #undef THIS_FILE
 static const char THIS_FILE[]=__FILE__;
 #endif
+static bool needUniqueCheck(Index *index, Record *record);
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
@@ -347,15 +348,6 @@ void Table::insert(Transaction *transact
 		// Make insert/update atomic, then check for unique index duplicats
 		
 		recordNumber = record->recordNumber = dbb->insertStub(dataSection, transaction);
-		
-		if (indexes)
-			{
-			checkUniqueIndexes(transaction, record);
-
-			FOR_INDEXES(index, this);
-				index->insert(record, transaction);
-			END_FOR;
-			}
 
 		// Verify that record is valid
 
@@ -363,7 +355,7 @@ void Table::insert(Transaction *transact
 		transaction->addRecord(record);
 		insert(record, NULL, recordNumber);
 		inserted = true;
-		
+		insertIndexes(transaction, record);
 		updateInversion(record, transaction);
 		fireTriggers(transaction, PostInsert, NULL, record);
 		record->release();
@@ -999,7 +991,7 @@ Record* Table::rollbackRecord(RecordVers
 			
 		recordToRollback->printRecord("Table::rollbackRecord");
 		insert(priorRecord, recordToRollback, recordToRollback->recordNumber);
-		ASSERT(false);
+		//ASSERT(false);
 		}
 
 	if (!priorRecord && recordToRollback->recordNumber >= 0)
@@ -1182,6 +1174,57 @@ void Table::makeNotSearchable(Field *fie
 	database->flushInversion(transaction);
 }
 
+/**
+@brief		index update , combined with unique check (atomic)
+
+		Determine if the record we intend to write will have a duplicate conflict
+			with any pending or visible records.
+@details	For each  unique index, obtain an exclusive lock and check the index
+			update index if the search succeeded by not finding a duplicate.
+			Retry if a wait occurred.
+			If a duplicate is found, an exception should be caught by the caller.
+		non-unique indexes are  updated without any check
+**/
+void Table::updateIndexes(Transaction *transaction, RecordVersion *record, Record
*oldRecord)
+{
+	if (indexes)
+	{
+	FOR_INDEXES(index, this);
+		Sync sync(&(index->syncUnique), "Table::updateIndexes");
+		if(needUniqueCheck(index,record))
+			for(;;)
+			{
+			sync.lock(Exclusive);
+			if (!checkUniqueIndex(index, transaction, record , &sync))
+				break;
+			}
+		index->update(oldRecord, record, transaction);
+	END_FOR;
+	}
+}
+
+/**
+@brief		Uniqueness check combined with index insert (atomic)
+**/
+void Table::insertIndexes(Transaction *transaction, RecordVersion *record)
+{
+	if (indexes)
+	{
+	FOR_INDEXES(index, this);
+		Sync sync(&(index->syncUnique), "Table::insertIndexes");
+		if(needUniqueCheck(index,record))
+			for(;;)
+			{
+			sync.lock(Exclusive);
+			if(!checkUniqueIndex(index, transaction, record, &sync))
+				break;
+			}
+		index->insert(record, transaction);
+	END_FOR;
+	}
+}
+
+
 void Table::update(Transaction * transaction, Record * oldRecord, int numberFields,
Field** updateFields, Value * * values)
 {
 	database->preUpdate();
@@ -1243,19 +1286,12 @@ void Table::update(Transaction * transac
 		
 		// Make insert/update atomic, then check for unique index duplicats
 
-		if (indexes)
-			{
-			checkUniqueIndexes(transaction, record);
-
-			FOR_INDEXES(index, this);
-				index->update(oldRecord, record, transaction);
-			END_FOR;
-			}
 
 		scavenge.lock(Shared);
 		validateAndInsert(transaction, record);
 		transaction->addRecord(record);
 		updated = true;
+		updateIndexes(transaction, record, oldRecord);
 
 		updateInversion(record, transaction);
 		fireTriggers(transaction, PostUpdate, oldRecord, record);
@@ -2415,40 +2451,7 @@ bool Table::isDuplicate(Index *index, Re
 
 	return true;
 }
-/**
-@brief		Determine if the record we intend to write will have a duplicate conflict
-			with any pending or visible records.
-@details	For each index, call checkUniqueIndex.  
-			Return if the search succeeded by not finding a duplicate.
-			Retry if a wait occurred.
-			If a duplicate is found, an exception should be caught by the caller.
-**/
-
-void Table::checkUniqueIndexes(Transaction *transaction, RecordVersion *record)
-{
-	Record *oldRecord = record->getPriorVersion();
-	bool retry = true;
 
-	while (retry)
-		{
-		retry = false;
-		FOR_INDEXES(index, this);
-			{
-			if (INDEX_IS_UNIQUE(index->type) &&
-				(!oldRecord || index->changed(record, oldRecord)))
-				{
-				retry = checkUniqueIndex(index, transaction, record);
-				if (retry)
-					break;
-				}
-			if (retry)
-				break;
-			}
-		END_FOR;
-		}
-
-	return;
-}
 
 /**
 @brief		Determine if the record we intend to write will have a duplicate conflict
@@ -2458,7 +2461,7 @@ void Table::checkUniqueIndexes(Transacti
 			Return false if no duplicate was found.
 **/
 
-bool Table::checkUniqueIndex(Index *index, Transaction *transaction, RecordVersion
*record)
+bool Table::checkUniqueIndex(Index *index, Transaction *transaction, RecordVersion
*record, Sync *sync)
 {
 	Bitmap bitmap;
 	IndexKey indexKey(index);
@@ -2467,7 +2470,7 @@ bool Table::checkUniqueIndex(Index *inde
 
 	for (int32 recordNumber = 0; (recordNumber = bitmap.nextSet(recordNumber)) >= 0;
++recordNumber)
 		{
-		int retry = checkUniqueRecordVersion(recordNumber, index, transaction, record);
+		int retry = checkUniqueRecordVersion(recordNumber, index, transaction, record, sync);
 		
 		if (retry)
 			return true;  // restart the search since a wait occurred.
@@ -2485,7 +2488,7 @@ bool Table::checkUniqueIndex(Index *inde
 			Throw an exception if a duplicate WAS found
 **/
 
-bool Table::checkUniqueRecordVersion(int32 recordNumber, Index *index, Transaction
*transaction, RecordVersion *record)
+bool Table::checkUniqueRecordVersion(int32 recordNumber, Index *index, Transaction
*transaction, RecordVersion *record, Sync *syncUnique)
 {
 	Record *rec;
 	Record *oldRecord = record->getPriorVersion();
@@ -2578,7 +2581,8 @@ bool Table::checkUniqueRecordVersion(int
 			if (state == Active)
 				{
 				syncPrior.unlock(); // release lock before wait
-				
+				syncUnique->unlock(); // release lock before wait
+
 				// Wait for that transaction, then restart checkUniqueIndexes()
 
 				state = transaction->getRelativeState(dup, WAIT_IF_ACTIVE);
@@ -2597,6 +2601,7 @@ bool Table::checkUniqueRecordVersion(int
 			else if (activeTransaction)
 				{
 				syncPrior.unlock(); // release lock before wait
+				syncUnique->unlock(); // release lock before wait
 
 				state = transaction->getRelativeState(activeTransaction,
 						activeTransaction->transactionId, WAIT_IF_ACTIVE);
@@ -2998,21 +3003,15 @@ uint Table::insert(Transaction *transact
 		
 		// Make insert/update atomic, then check for unique index duplicats
 
-		if (indexes)
-			{
-			checkUniqueIndexes(transaction, record);
-
-			FOR_INDEXES(index, this);
-				index->insert (record, transaction);
-			END_FOR;
-			}
 
 		// Do the actual insert
 
 		transaction->addRecord(record);
 		bool ret = insert(record, NULL, recordNumber);
-		ASSERT(ret);
 		inserted = true;
+		insertIndexes(transaction, record);
+		ASSERT(ret);
+
 
 		record->release();
 		}
@@ -3121,16 +3120,7 @@ void Table::update(Transaction * transac
 				attachment->preUpdate(this, record);
 		END_FOR;
 
-		// Make insert/update atomic, then check for unique index duplicats
-
-		if (indexes)
-			{
-			checkUniqueIndexes(transaction, record);
 
-			FOR_INDEXES(index, this);
-				index->update(oldRecord, record, transaction);
-			END_FOR;
-			}
 
 		//updateInversion(record, transaction);
 		scavenge.lock(Shared);
@@ -3144,6 +3134,8 @@ void Table::update(Transaction * transac
 			}
 
 		updated = true;
+		// Make insert/update atomic, then check for unique index duplicats
+		updateIndexes(transaction, record, oldRecord);
 		//fireTriggers(transaction, PostUpdate, oldRecord, record);
 
 		// If this is a re-update in the same transaction and the same savepoint,
@@ -3772,3 +3764,11 @@ SyncObject* Table::getSyncPrior(int reco
 	return syncPriorVersions + lockNumber;
 }
 
+
+static bool needUniqueCheck(Index *index, Record *record)
+{
+	Record *oldRecord = record->getPriorVersion();
+	return (INDEX_IS_UNIQUE(index->type) &&
+		(!oldRecord || index->changed(record, oldRecord)));
+
+}
diff -Nrup a/storage/falcon/Table.h b/storage/falcon/Table.h
--- a/storage/falcon/Table.h	2008-04-09 10:23:49 +02:00
+++ b/storage/falcon/Table.h	2008-04-16 14:14:48 +02:00
@@ -103,8 +103,8 @@ public:
 	void		makeNotSearchable (Field *field, Transaction *transaction);
 	bool		dropForeignKey (int fieldCount, Field **fields, Table *references);
 	void		checkUniqueIndexes (Transaction *transaction, RecordVersion *record);
-	bool		checkUniqueIndex(Index *index, Transaction *transaction, RecordVersion *record);
-	bool		checkUniqueRecordVersion(int32 recordNumber, Index *index, Transaction
*transaction, RecordVersion *record);
+	bool		checkUniqueIndex(Index *index, Transaction *transaction, RecordVersion *record,
Sync *sync);
+	bool		checkUniqueRecordVersion(int32 recordNumber, Index *index, Transaction
*transaction, RecordVersion *record, Sync *sync);
 	bool		isDuplicate (Index *index, Record *record1, Record *record2);
 	void		checkDrop();
 	Field*		findField (const WCString *fieldName);
@@ -208,9 +208,11 @@ public:
 	void			insert (Transaction *transaction, int count, Field **fields, Value **values);
 	uint			insert (Transaction *transaction, Stream *stream);
 	bool			insert (Record *record, Record *prior, int recordNumber);
+	void			insertIndexes(Transaction *transaction, RecordVersion *record);
 	
 	void			update (Transaction *transaction, Record *record, int numberFields, Field
**fields, Value** values);
 	void			update(Transaction * transaction, Record *oldRecord, Stream *stream);
+	void			updateIndexes(Transaction *transaction, RecordVersion *record, Record
*oldRecord);
 	
 	void			deleteRecord (Transaction *transaction, Record *record);
 	void			deleteRecord (int recordNumber);
Thread
bk commit into 6.0 tree (vvaintroub:1.2642) BUG#35322vvaintroub16 Apr 2008
  • RE: bk commit into 6.0 tree (vvaintroub:1.2642) BUG#35322Kevin Lewis18 Apr 2008
    • RE: bk commit into 6.0 tree (vvaintroub:1.2642) BUG#35322Vladislav Vaintroub18 Apr 2008