List:Commits« Previous MessageNext Message »
From:cpowers Date:April 9 2008 10:23am
Subject:bk commit into 6.0 tree (cpowers:1.2632) BUG#35692
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of cpowers.  When cpowers 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-09 03:23:51-05:00, cpowers@stripped +13 -0
  Bug#35692, "Running falcon_record_cache_memory_leak2-big.test crashes Falcon"
  
  Serialized acces to prior record versions using an array of syncObjects,
Table::syncPriorVersions[].
  
  Elements of syncPriorVersions[] are assigned according to record number.
  
  Methods that require read-only access to prior record versions now acquire
  a shared lock on the corresponding syncPriorVersion[] sync object. Methods
  requiring write access acquire an exclusive lock.
  
  RecordVersion::priorVersion is now accessed strictly through
RecordVersion::getPriorVersion().

  storage/falcon/ImageManager.cpp@stripped, 2008-04-09 03:21:19-05:00, cpowers@stripped
+1 -1
    Encapsulated RecordVersion::priorVersion.

  storage/falcon/Record.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +5 -0
    Added getSyncPrior().

  storage/falcon/Record.h@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +2 -0
    Added getSyncPrior().

  storage/falcon/RecordLeaf.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +6
-0
    Added prior record version locks.

  storage/falcon/RecordVersion.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped
+12 -2
    Added prior record version locks.
    Added getSyncPrior().

  storage/falcon/RecordVersion.h@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +3
-1
    Moved priorVersion from public to protected.
    Added getSyncPrior().

  storage/falcon/SRLUpdateRecords.cpp@stripped, 2008-04-09 03:23:49-05:00,
cpowers@stripped +1 -1
    Encapsulated RecordVersion::priorVersion.

  storage/falcon/SyncObject.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped
+16 -1
    SyncObject::name is now a copy of the incoming name string.

  storage/falcon/SyncObject.h@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +1 -1
    SyncObject::name is now a copy of the incoming name string.

  storage/falcon/Table.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +126
-49
    Added "syncPriorVersions[]", an array of SyncObjects for serializing
    access to chains of prior record versions.
    
    Replaced direct access to RecordVersion::priorVersion with getPriorVersion().
    
    Added shared prior version record locks to functions that scan prior record version
chains.
    Added exclusive locks to functions that modify record version chains.
    
    Added Table::getSyncPrior() that returns a SyncObject from Table::syncPriorVersions[]
according
    to record number.

  storage/falcon/Table.h@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped +6 -0
    Added syncPriorVersions[] and getSyncPrior().

  storage/falcon/TableAttachment.cpp@stripped, 2008-04-09 03:23:49-05:00,
cpowers@stripped +2 -2
    Encapsulated RecordVersion::priorVersion.

  storage/falcon/Transaction.cpp@stripped, 2008-04-09 03:23:49-05:00, cpowers@stripped
+3 -3
    Encapsulated RecordVersion::priorVersion.

diff -Nrup a/storage/falcon/ImageManager.cpp b/storage/falcon/ImageManager.cpp
--- a/storage/falcon/ImageManager.cpp	2008-03-03 12:40:14 -06:00
+++ b/storage/falcon/ImageManager.cpp	2008-04-09 03:21:19 -05:00
@@ -233,7 +233,7 @@ void ImageManager::checkAccess(Table *ta
 		heightId = table->getFieldId ("HEIGHT");
 		}
 
-	Record *record = (recordVersion->hasRecord()) ? recordVersion :
recordVersion->priorVersion;
+	Record *record = (recordVersion->hasRecord()) ? recordVersion :
recordVersion->getPriorVersion();
 	ValueEx application (record, applicationId);
 	Table *images = database->findTable (application.getString(), "IMAGES");
 	Transaction *transaction = recordVersion->transaction;
diff -Nrup a/storage/falcon/Record.cpp b/storage/falcon/Record.cpp
--- a/storage/falcon/Record.cpp	2008-03-30 02:24:27 -05:00
+++ b/storage/falcon/Record.cpp	2008-04-09 03:23:49 -05:00
@@ -947,3 +947,8 @@ int Record::getSize(void)
 {
 	return sizeof(*this);
 }
+
+SyncObject* Record::getSyncPrior(void)
+{
+	return NULL;
+}
diff -Nrup a/storage/falcon/Record.h b/storage/falcon/Record.h
--- a/storage/falcon/Record.h	2008-03-30 02:24:27 -05:00
+++ b/storage/falcon/Record.h	2008-04-09 03:23:49 -05:00
@@ -62,6 +62,7 @@ class Stream;
 class Database;
 class RecordScavenge;
 class Serialize;
+class SyncObject;
 CLASS(Field);
 
 extern char	*RecordAllocate (int size, const char *file, int line);
@@ -90,6 +91,7 @@ public:
 	virtual int		setRecordData(const UCHAR *dataIn, int dataLength);
 	virtual void	serialize(Serialize* stream);
 	virtual int		getSize(void);
+	virtual SyncObject* getSyncPrior(void);
 
 	const UCHAR*	getEncoding (int index);
 	int				setEncodedRecord(Stream *stream, bool interlocked);
diff -Nrup a/storage/falcon/RecordLeaf.cpp b/storage/falcon/RecordLeaf.cpp
--- a/storage/falcon/RecordLeaf.cpp	2008-03-31 17:00:49 -05:00
+++ b/storage/falcon/RecordLeaf.cpp	2008-04-09 03:23:49 -05:00
@@ -134,6 +134,9 @@ int RecordLeaf::retireRecords (Table *ta
 				++count;
 			else if (record->isVersion())
 				{
+				Sync syncPrior(record->getSyncPrior(), "RecordVersion::scavenge");
+				syncPrior.lock(Shared);
+	
 				if (record->scavenge(recordScavenge, Shared))
 				    break;
 				else
@@ -164,6 +167,9 @@ int RecordLeaf::retireRecords (Table *ta
 			{
 			if (record->isVersion())
 				{
+				Sync syncPrior(record->getSyncPrior(), "RecordVersion::scavenge");
+				syncPrior.lock(Exclusive);
+				
 				if (record->scavenge(recordScavenge, Exclusive))
 					{
 					*ptr = NULL;
diff -Nrup a/storage/falcon/RecordVersion.cpp b/storage/falcon/RecordVersion.cpp
--- a/storage/falcon/RecordVersion.cpp	2008-04-08 02:06:46 -05:00
+++ b/storage/falcon/RecordVersion.cpp	2008-04-09 03:23:49 -05:00
@@ -238,6 +238,9 @@ void RecordVersion::scavenge(TransId tar
 	if (!priorVersion)
 		return;
 
+	Sync syncPrior(getSyncPrior(), "RecordVersion::scavenge(2)");
+	syncPrior.lock(Exclusive);
+	
 	Record *rec = priorVersion;
 	Record *ptr = NULL;
 	
@@ -300,10 +303,12 @@ bool RecordVersion::isSuperceded()
 void RecordVersion::setPriorVersion(Record *oldVersion)
 {
 	if (oldVersion)
+		{
 		oldVersion->addRef();
 
-	if (priorVersion)
-		priorVersion->release();
+		if (priorVersion)
+			priorVersion->release();
+		}
 
 	priorVersion = oldVersion;
 }
@@ -438,4 +443,9 @@ void RecordVersion::serialize(Serialize*
 		}
 	else
 		stream->putInt(2);
+}
+
+SyncObject* RecordVersion::getSyncPrior()
+{
+	return format->table->getSyncPrior(this);
 }
diff -Nrup a/storage/falcon/RecordVersion.h b/storage/falcon/RecordVersion.h
--- a/storage/falcon/RecordVersion.h	2008-03-30 02:24:27 -05:00
+++ b/storage/falcon/RecordVersion.h	2008-04-09 03:23:49 -05:00
@@ -27,6 +27,7 @@
 #include "Record.h"
 
 class Transaction;
+class SyncObject;
 
 class RecordVersion : public Record  
 {
@@ -54,16 +55,17 @@ public:
 	virtual void		print(void);
 	virtual int			getSize(void);
 	virtual void		serialize(Serialize* stream);
+	virtual SyncObject* getSyncPrior();
 
 	void				commit();
 
 protected:
 	virtual ~RecordVersion();
+	Record			*priorVersion;
 
 public:
 	uint64			virtualOffset;		// byte offset into serial log window
 	Transaction		*transaction;
-	Record			*priorVersion;
 	RecordVersion	*nextInTrans;
 	RecordVersion	*prevInTrans;
 	TransId			transactionId;
diff -Nrup a/storage/falcon/SRLUpdateRecords.cpp b/storage/falcon/SRLUpdateRecords.cpp
--- a/storage/falcon/SRLUpdateRecords.cpp	2008-03-11 10:16:31 -05:00
+++ b/storage/falcon/SRLUpdateRecords.cpp	2008-04-09 03:23:49 -05:00
@@ -215,7 +215,7 @@ void SRLUpdateRecords::append(Transactio
 			uint32 sectionId = table->dataSectionId;
 			log->updateSectionUseVector(sectionId, tableSpaceId, 1);
 			putInt(tableSpaceId);
-			putInt((record->priorVersion) ? sectionId : -(int) sectionId - 1);
+			putInt(record->getPriorVersion() ? sectionId : -(int) sectionId - 1);
 			putInt(record->recordNumber);
 			putStream(&stream);
 			
diff -Nrup a/storage/falcon/SyncObject.cpp b/storage/falcon/SyncObject.cpp
--- a/storage/falcon/SyncObject.cpp	2008-03-31 17:00:55 -05:00
+++ b/storage/falcon/SyncObject.cpp	2008-04-09 03:23:49 -05:00
@@ -127,6 +127,9 @@ SyncObject::~SyncObject()
 #ifdef TRACE_SYNC_OBJECTS
 	if (objectId < MAX_SYNC_OBJECTS)
 		syncObjects[objectId] = NULL;
+		
+	if (name)
+		delete [] name;
 #endif
 }
 
@@ -694,7 +697,19 @@ void SyncObject::getSyncInfo(InfoTable* 
 void SyncObject::setName(const char* string)
 {
 #ifdef TRACE_SYNC_OBJECTS
-	name = string;
+	if (name)
+		{
+		delete [] name;
+		name = NULL;
+		}
+	
+	if (string)
+		{
+		name = new char[strlen(string)+1];
+		strcpy(name, string);
+		}
+		
+	//name = string;
 #endif
 }
 
diff -Nrup a/storage/falcon/SyncObject.h b/storage/falcon/SyncObject.h
--- a/storage/falcon/SyncObject.h	2008-03-11 10:16:31 -05:00
+++ b/storage/falcon/SyncObject.h	2008-04-09 03:23:49 -05:00
@@ -105,7 +105,7 @@ protected:
 	int					waitCount;
 	int					queueLength;
 	const char*			where;
-	const char*			name;
+	char*				name;
 #endif
 };
 
diff -Nrup a/storage/falcon/Table.cpp b/storage/falcon/Table.cpp
--- a/storage/falcon/Table.cpp	2008-03-30 02:24:27 -05:00
+++ b/storage/falcon/Table.cpp	2008-04-09 03:23:49 -05:00
@@ -738,7 +738,6 @@ void Table::loadFields()
 	buildFieldVector();
 	resultSet->close();
 	statement->close();
-
 }
 
 void Table::loadIndexes()
@@ -822,6 +821,14 @@ void Table::init(int id, const char *sch
 	activeVersions = false;
 	primaryKey = NULL;
 	formats = NEW Format* [FORMAT_HASH_SIZE];
+
+	for (int n = 0; n < SYNC_VERSIONS_SIZE; n++)
+		{
+		char name[64];
+		sprintf(name, "syncPriorVersions[%02d]", n);
+		syncPriorVersions[n].setName(name);
+		}
+		
 	triggers = NULL;
 	memset (formats, 0, sizeof (Format*) * FORMAT_HASH_SIZE);
 	maxFieldId = 0;
@@ -956,6 +963,15 @@ Record* Table::backlogFetch(int32 record
 
 Record* Table::rollbackRecord(RecordVersion * recordToRollback, Transaction *transaction)
 {
+	Sync * syncPrior = NULL;
+	
+	 //cwp tbd: Problem if systemConnection->rollback() and table deleted
+	if (!transaction->systemTransaction)
+		{
+		syncPrior = NEW Sync(getSyncPrior(recordToRollback), "Table::rollbackRecord");
+		syncPrior->lock(Shared);
+		}
+	
 #ifdef CHECK_RECORD_ACTIVITY
 	recordToRollback->active = false;
 #endif
@@ -965,7 +981,7 @@ Record* Table::rollbackRecord(RecordVers
 
 	// Find the record that will become the current version.
 
-	Record *priorRecord = recordToRollback->priorVersion;
+	Record *priorRecord = recordToRollback->getPriorVersion();
 
 	if (priorRecord)
 		priorRecord->setSuperceded(false);
@@ -989,6 +1005,9 @@ Record* Table::rollbackRecord(RecordVers
 
 	if (backloggedRecords)
 		deleteRecordBacklog(recordToRollback->recordNumber);
+		
+	if (syncPrior)
+		delete syncPrior;
 			
 	return priorRecord;
 }
@@ -1134,7 +1153,6 @@ void Table::makeSearchable(Field * field
 	database->flushInversion(transaction);
 }
 
-
 void Table::makeNotSearchable(Field *field, Transaction *transaction)
 {
 	Record *record;
@@ -1257,8 +1275,8 @@ void Table::update(Transaction * transac
 		
 		if (record)
 			{
-			if (record->priorVersion)
-				record->priorVersion->setSuperceded(false);
+			if (record->getPriorVersion())
+				record->getPriorVersion()->setSuperceded(false);
 								
 			if (record->state == recLock)
 				record->deleteData();
@@ -1286,24 +1304,29 @@ void Table::reIndexInversion(Transaction
 		return;
 
 	Record *record;
-
+	
 	for (int32 next = 0; (record = fetchNext(next));)
 		{
 		next = record->recordNumber + 1;
 		
-		for (Record *version = record; version; version = version->getPriorVersion())
-			if (version->hasRecord())
-				FOR_FIELDS(field, this)
-					if (field->flags & SEARCHABLE)
-						{
-						Value value;
-						version->getValue(field->id, &value);
-						Filter stream(tableId, field->id, version->recordNumber, &value);
-						//value.getStream(&stream, false);
-						database->addInversion(&stream, transaction);
-						}
-				END_FOR;
-				
+		{
+			Sync syncPrior(getSyncPrior(record->recordNumber), "Table::reIndexInversion");
+			syncPrior.lock(Shared);
+	
+			for (Record *version = record; version; version = version->getPriorVersion())
+				if (version->hasRecord())
+					FOR_FIELDS(field, this)
+						if (field->flags & SEARCHABLE)
+							{
+							Value value;
+							version->getValue(field->id, &value);
+							Filter stream(tableId, field->id, version->recordNumber, &value);
+							//value.getStream(&stream, false);
+							database->addInversion(&stream, transaction);
+							}
+					END_FOR;
+		}
+			
 		record->release();
 		}
 }
@@ -1389,6 +1412,10 @@ void Table::deleteRecord(Transaction * t
 {
 	database->preUpdate();
 	Sync scavenge(&syncScavenge, "Table::deleteRecord");
+
+	Sync syncPrior(getSyncPrior(orgRecord), "Table::deleteRecord");
+	syncPrior.lock(Shared);
+	
 	Record *candidate = fetch(orgRecord->recordNumber);
 	checkAncestor(candidate, orgRecord);
 	RecordVersion *record;
@@ -1402,7 +1429,7 @@ void Table::deleteRecord(Transaction * t
 		if (candidate->getSavePointId() == transaction->curSavePointId)
 			{
 			record = (RecordVersion*) candidate;
-			ASSERT(record->priorVersion == orgRecord);
+			ASSERT(record->getPriorVersion() == orgRecord);
 			wasLock = true;
 			}
 		else
@@ -1577,7 +1604,8 @@ void Table::truncate(Transaction *transa
 	
 	// Update system.tables with new section ids and cardinality
 	
-	PreparedStatement *statement = database->prepareStatement("update system.tables set
dataSection=?, blobSection=?, cardinality=? where tableId=?");
+	PreparedStatement *statement = database->prepareStatement (	"update system.tables set
dataSection=?,"
+																" blobSection=?, cardinality=? where tableId=?");
 	statement->setInt(1, dataSectionId);
 	statement->setInt(2, blobSectionId);
 	statement->setLong(3, cardinality);
@@ -1717,9 +1745,14 @@ void Table::populateIndex(Index * index,
 		{
 		next = record->recordNumber + 1;
 
-		for (Record *version = record; version; version = version->getPriorVersion())
-			if (version->hasRecord())
-				index->insert(version, transaction);
+		{
+			Sync syncPrior(getSyncPrior(record->recordNumber), "Table::populateIndex");
+			syncPrior.lock(Shared);
+		
+			for (Record *version = record; version; version = version->getPriorVersion())
+				if (version->hasRecord())
+					index->insert(version, transaction);
+		}
 
 		record->release();
 
@@ -1877,8 +1910,13 @@ bool Table::insert(Record * record, Reco
 void Table::expungeRecordVersions(RecordVersion *record, RecordScavenge *recordScavenge)
 {
 	ASSERT(record->state != recLock);
-	Record *prior = record->priorVersion;
-	record->priorVersion = NULL;
+
+	Sync syncPrior(getSyncPrior(record), "Table::expungeRecordVersions");
+	syncPrior.lock(Exclusive);
+	
+	Record *prior = record->getPriorVersion();
+	//record->priorVersion = NULL;
+	record->setPriorVersion(NULL);
 	
 	if (recordScavenge)
 		for (Record *rec = prior; rec; rec = rec->getPriorVersion())
@@ -1930,6 +1968,9 @@ bool Table::duplicateBlob(Value * blob, 
 			return isDuplicate;
 		}
 
+	Sync syncPrior(getSyncPrior(recordChain), "Table::duplicateBlob");
+	syncPrior.lock(Shared);
+	
 	for (Record *record = recordChain; record; record = record->getPriorVersion())
 		if (record->hasRecord())
 			{
@@ -2009,6 +2050,9 @@ void Table::expungeBlob(Value * blob)
 
 void Table::garbageCollect(Record * leaving, Record * staying, Transaction *transaction,
bool quiet)
 {
+	Sync syncPrior(getSyncPrior(leaving), "Table::garbageCollect");
+	syncPrior.lock(Shared);
+	
 	// Clean up field indexes
 
 	FOR_INDEXES(index, this);
@@ -2200,7 +2244,7 @@ void Table::postCommit(Transaction *tran
 
 	try
 		{
-		fireTriggers(transaction, PostCommit, record->priorVersion, after);
+		fireTriggers(transaction, PostCommit, record->getPriorVersion(), after);
 		}
 	catch (...)
 		{
@@ -2380,7 +2424,7 @@ bool Table::isDuplicate(Index *index, Re
 
 void Table::checkUniqueIndexes(Transaction *transaction, RecordVersion *record)
 {
-	Record *oldRecord = record->priorVersion;
+	Record *oldRecord = record->getPriorVersion();
 	bool retry = true;
 
 	while (retry)
@@ -2442,7 +2486,7 @@ bool Table::checkUniqueIndex(Index *inde
 bool Table::checkUniqueRecordVersion(int32 recordNumber, Index *index, Transaction
*transaction, RecordVersion *record)
 {
 	Record *rec;
-	Record *oldRecord = record->priorVersion;
+	Record *oldRecord = record->getPriorVersion();
 	Transaction *activeTransaction = NULL;
 	State state = CommittedVisible;
 
@@ -2725,16 +2769,21 @@ void Table::validateBlobs(int optionMask
 		{
 		next = record->recordNumber + 1;
 		
-		for (Record *version = record; version; version = version->getPriorVersion())
-			if (version->hasRecord())
-				for (field = fields; field; field = field->next)
-					if (field->type == Asciiblob || field->type == Binaryblob)
-						{
-						int id = version->getBlobId(field->id);
-						
-						if (id >= 0)
-							references.set (id);
-						}
+		{
+			Sync syncPrior(getSyncPrior(record->recordNumber), "Table::validateBlobs");
+			syncPrior.lock(Shared);
+		
+			for (Record *version = record; version; version = version->getPriorVersion())
+				if (version->hasRecord())
+					for (field = fields; field; field = field->next)
+						if (field->type == Asciiblob || field->type == Binaryblob)
+							{
+							int id = version->getBlobId(field->id);
+					
+							if (id >= 0)
+								references.set (id);
+							}
+		}
 						
 		record->release();
 		}
@@ -2987,6 +3036,7 @@ uint Table::insert(Transaction *transact
 void Table::update(Transaction * transaction, Record *orgRecord, Stream *stream)
 {
 	database->preUpdate();
+	
 	Record *candidate = fetch(orgRecord->recordNumber);
 	checkAncestor(candidate, orgRecord);
 	
@@ -3111,8 +3161,8 @@ void Table::update(Transaction * transac
 	
 		if (record)
 			{
-			if (record->priorVersion)
-				record->priorVersion->setSuperceded(false);
+			if (record->getPriorVersion())
+				record->getPriorVersion()->setSuperceded(false);
 								
 			if (record->state == recLock)
 				record->deleteData();
@@ -3126,7 +3176,6 @@ void Table::update(Transaction * transac
 		}
 }
 
-
 void Table::rename(const char *newSchema, const char *newName)
 {
 	try
@@ -3214,14 +3263,17 @@ JString Table::getPrimaryKeyName(void)
 
 void Table::validateAndInsert(Transaction *transaction, RecordVersion *record)
 {
-	Sync sync(&syncObject, "Table::validateAndInsert");
+	Sync syncTable(&syncObject, "Table::validateAndInsert");
+	Sync syncPrior(getSyncPrior(record), "Table::validateAndInsert");
+	
 	Record *prior = record->getPriorVersion();
-
+	
 	for (int n = 0; n < 10; ++n)
 		{
 		if (prior)
 			{
-			sync.lock(Exclusive);
+			syncTable.lock(Exclusive);
+			syncPrior.lock(Shared);
 			Record *current = fetch(record->recordNumber);
 
 			if (current)
@@ -3236,10 +3288,13 @@ void Table::validateAndInsert(Transactio
 
 					TransId transId = current->getTransactionId();
 					current->release();
-					sync.unlock();
+					syncPrior.unlock();
+					syncTable.unlock();
 
 					if (transaction->waitForTransaction(transId))
 						{
+						syncTable.lock(Exclusive);
+						syncPrior.lock(Shared);
 						current = fetch(record->recordNumber);
 						
 						if (current == prior)
@@ -3262,7 +3317,7 @@ void Table::validateAndInsert(Transactio
 			
 		record->active = false;
 		}
-
+		
 	throw SQLError(UPDATE_CONFLICT, "unexpected update conflict in table %s.%s record %d",
schemaName, name, record->recordNumber);
 }
 
@@ -3342,13 +3397,13 @@ void Table::unlockRecord(int recordNumbe
 void Table::unlockRecord(RecordVersion* record, bool remove)
 {
 	//int uc = record->useCount;
-	ASSERT(record->priorVersion);
+	ASSERT(record->getPriorVersion());
 	
 	if (record->state == recLock)
 		{
 		record->state = recUnlocked;
 
-		if (insert(record->priorVersion, record, record->recordNumber))
+		if (insert(record->getPriorVersion(), record, record->recordNumber))
 			{
 			if (remove && record->transaction)
 				record->transaction->removeRecord(record);
@@ -3360,6 +3415,9 @@ void Table::unlockRecord(RecordVersion* 
 
 void Table::checkAncestor(Record* current, Record* oldRecord)
 {
+	Sync syncPrior(getSyncPrior(current), "Table::checkAncestor");
+	syncPrior.lock(Shared);
+	
 	for (Record *record = current; record; record = record->getPriorVersion())
 		if (record == oldRecord)
 			return;
@@ -3398,6 +3456,9 @@ Record* Table::fetchForUpdate(Transactio
 		if (record->state != recLock)
 			return record;
 
+		Sync syncPrior(getSyncPrior(record), "Table::fetchForUpdate(1)");
+		syncPrior.lock(Shared);
+	
 		Record *prior = record->getPriorVersion();
 		prior->addRef();
 		record->release();
@@ -3601,6 +3662,9 @@ bool Table::validateUpdate(int32 recordN
 	if (deleting)
 		return false;
 
+	Sync syncPrior(getSyncPrior(recordNumber), "Table::validateUpdate");
+	syncPrior.lock(Shared);
+	
 	Record *record = treeFetch(recordNumber);
 	Record *initial = record;
 	
@@ -3687,3 +3751,16 @@ void Table::deleteRecordBacklog(int32 re
 		database->backLog->deleteRecord(backlogId);
 		}
 }
+
+SyncObject* Table::getSyncPrior(Record* record)
+{
+	int lockNumber = record->recordNumber % SYNC_VERSIONS_SIZE;
+	return &syncPriorVersions[lockNumber];
+}
+
+SyncObject* Table::getSyncPrior(int recordNumber)
+{
+	int lockNumber = recordNumber % SYNC_VERSIONS_SIZE;
+	return &syncPriorVersions[lockNumber];
+}
+
diff -Nrup a/storage/falcon/Table.h b/storage/falcon/Table.h
--- a/storage/falcon/Table.h	2008-03-24 22:54:50 -05:00
+++ b/storage/falcon/Table.h	2008-04-09 03:23:49 -05:00
@@ -42,6 +42,7 @@ static const int PostCommit	= 128;
 
 static const int BL_SIZE			= 128;
 static const int FORMAT_HASH_SIZE	= 20;
+static const int SYNC_VERSIONS_SIZE	= 16;
 
 #define FOR_FIELDS(field,table)	{for (Field *field=table->fields; field; field =
field->next){
 #define FOR_INDEXES(index,table)	{for (Index *index=table->indexes; index; index =
index->next){
@@ -214,12 +215,17 @@ public:
 	void			deleteRecord (Transaction *transaction, Record *record);
 	void			deleteRecord (int recordNumber);
 	void			deleteRecord (RecordVersion *record, Transaction *transaction);
+	
+	SyncObject*		getSyncPrior(Record* record);
+	SyncObject*		getSyncPrior(int recordNumber);
+	
 
 	Dbb				*dbb;
 	SyncObject		syncObject;
 	SyncObject		syncTriggers;
 	SyncObject		syncScavenge;
 	SyncObject		syncAlter;				// prevent concurrent Alter statements.
+	SyncObject		syncPriorVersions[SYNC_VERSIONS_SIZE];
 	Table			*collision;				// Hash collision in database
 	Table			*idCollision;			// mod(id) collision in database
 	Table			*next;					// next in database linked list
diff -Nrup a/storage/falcon/TableAttachment.cpp b/storage/falcon/TableAttachment.cpp
--- a/storage/falcon/TableAttachment.cpp	2007-09-20 10:42:44 -05:00
+++ b/storage/falcon/TableAttachment.cpp	2008-04-09 03:23:49 -05:00
@@ -36,10 +36,10 @@ TableAttachment::~TableAttachment()
 
 void TableAttachment::postCommit(Table *table, RecordVersion * record)
 {
-	if (!record->priorVersion)
+	if (!record->getPriorVersion())
 		insertCommit (table, record);
 	else if (!record->hasRecord())
-		deleteCommit (table, record->priorVersion);
+		deleteCommit (table, record->getPriorVersion());
 	else
 		updateCommit (table, record);
 }
diff -Nrup a/storage/falcon/Transaction.cpp b/storage/falcon/Transaction.cpp
--- a/storage/falcon/Transaction.cpp	2008-04-08 02:06:47 -05:00
+++ b/storage/falcon/Transaction.cpp	2008-04-09 03:23:49 -05:00
@@ -292,7 +292,7 @@ void Transaction::commit()
 	syncActiveTransactions.unlock();
 	
 	for (RecordVersion *record = firstRecord; record; record = record->nextInTrans)
-		if (!record->priorVersion)
+		if (!record->getPriorVersion())
 			++record->format->table->cardinality;
 		else if (record->state == recDeleted &&
record->format->table->cardinality > 0)
 			--record->format->table->cardinality;
@@ -1315,7 +1315,7 @@ void Transaction::printBlocking(int leve
 			++locks;
 		else if (!record->hasRecord())
 			++deletes;
-		else if (record->priorVersion)
+		else if (record->getPriorVersion())
 			++updates;
 		else
 			++inserts;
@@ -1343,7 +1343,7 @@ void Transaction::printBlocking(int leve
 			what = "locked";
 		else if (!record->hasRecord())
 			what = "deleted";
-		else if (record->priorVersion)
+		else if (record->getPriorVersion())
 			what = "updated";
 		else
 			what = "inserted";
Thread
bk commit into 6.0 tree (cpowers:1.2632) BUG#35692cpowers9 Apr