From: Date: March 25 2008 4:55am Subject: bk commit into 6.0 tree (klewis:1.2608) BUG#35538 List-Archive: http://lists.mysql.com/commits/44371 X-Bug: 35538 Message-Id: <200803250355.m2P3tWee021398@mail.mysql.com> Below is the list of changes that have just been committed into a local 6.0 repository of klewis. When klewis 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-03-24 22:55:03-05:00, klewis@klewis-mysql. +10 -0 Bug#35538 - Fix three-way deadlock between scavenger, gopher and an insert by moving the call to Table::validateUpdate() up to the top of Section::updateRecord() so that it does not hold any locks on any BDBs. Also, prevent an inadvertent wakeup of an active gopher thread waiting on another syncObject. storage/falcon/Gopher.cpp@stripped, 2008-03-24 22:54:32-05:00, klewis@klewis-mysql. +4 -0 Prevent an inadvertent wakeup of an active gopher thread waiting on another syncObject. storage/falcon/IO.cpp@stripped, 2008-03-24 22:54:35-05:00, klewis@klewis-mysql. +0 -4 Cleanup storage/falcon/IndexPage.cpp@stripped, 2008-03-24 22:54:37-05:00, klewis@klewis-mysql. +0 -10 Cleanup storage/falcon/IndexPage.h@stripped, 2008-03-24 22:54:39-05:00, klewis@klewis-mysql. +0 -1 Cleanup storage/falcon/IndexRootPage.cpp@stripped, 2008-03-24 22:54:41-05:00, klewis@klewis-mysql. +0 -1 Cleanup storage/falcon/Section.cpp@stripped, 2008-03-24 22:54:43-05:00, klewis@klewis-mysql. +9 -8 Bug#35538 - Fix three-way deadlock between scavenger, gopher and an insert by moving the call to Table::validateUpdate() up to the top of Section::updateRecord() so that it does not hold any locks on any BDBs. storage/falcon/SerialLog.cpp@stripped, 2008-03-24 22:54:45-05:00, klewis@klewis-mysql. +7 -3 Prevent an inadvertent wakeup of an active gopher thread waiting on another syncObject. storage/falcon/SyncObject.cpp@stripped, 2008-03-24 22:54:47-05:00, klewis@klewis-mysql. +6 -4 Check for lockGranted before sleeping and throw a timedOut exception only if sleep actually timed out. storage/falcon/Table.cpp@stripped, 2008-03-24 22:54:48-05:00, klewis@klewis-mysql. +0 -4 Cleanup; Finish deleting all references to unused Table::syncObject storage/falcon/Table.h@stripped, 2008-03-24 22:54:50-05:00, klewis@klewis-mysql. +0 -1 Cleanup; Finish deleting all references to unused Table::syncObject diff -Nrup a/storage/falcon/Gopher.cpp b/storage/falcon/Gopher.cpp --- a/storage/falcon/Gopher.cpp 2007-10-25 17:06:45 -05:00 +++ b/storage/falcon/Gopher.cpp 2008-03-24 22:54:32 -05:00 @@ -54,7 +54,9 @@ void Gopher::gopherThread(void) log->unblockUpdates(); sync.unlock(); + active = false; workerThread->sleep(); + active = true; sync.lock(Exclusive); continue; @@ -63,7 +65,9 @@ void Gopher::gopherThread(void) SerialLogTransaction *transaction = log->pending.first; log->pending.remove(transaction); sync.unlock(); + transaction->doAction(); + sync.lock(Exclusive); log->inactions.append(transaction); diff -Nrup a/storage/falcon/IO.cpp b/storage/falcon/IO.cpp --- a/storage/falcon/IO.cpp 2008-03-12 07:15:13 -05:00 +++ b/storage/falcon/IO.cpp 2008-03-24 22:54:35 -05:00 @@ -66,10 +66,6 @@ static int getLinuxVersion(); #define O_SYNC 0 #endif -#ifndef O_SYNC -#define O_SYNC 0 -#endif - #ifndef LSEEK #define LSEEK lseek #define SEEK_OFFSET off_t diff -Nrup a/storage/falcon/IndexPage.cpp b/storage/falcon/IndexPage.cpp --- a/storage/falcon/IndexPage.cpp 2008-03-22 09:52:15 -05:00 +++ b/storage/falcon/IndexPage.cpp 2008-03-24 22:54:37 -05:00 @@ -385,8 +385,6 @@ Bdb* IndexPage::splitIndexPageMiddle(Dbb if (level == 0) splitKey->appendRecordNumber(recordNumber); - - // Split supernodes memset(split->superNodes,0, sizeof(split->superNodes)); @@ -420,7 +418,6 @@ Bdb* IndexPage::splitIndexPageMiddle(Dbb return splitBdb; } - Btn* IndexPage::findNodeInBranch(IndexKey *searchKey, int32 searchRecordNumber) { ASSERT(level > 0); @@ -443,7 +440,6 @@ Btn* IndexPage::findNodeInBranch(IndexKe for (IndexNode node(super) ; node.node < bucketEnd ; prior = node.node, node.getNext(bucketEnd)) { - if (node.offset < matchedOffset) return prior; @@ -580,11 +576,9 @@ void IndexPage::validate(void *before) FATAL("node not correctly prefix-compressed"); } - if(node.length == 0 && recordNumber < priorRecordNumber) FATAL ("Index validate: record numbers out of order"); - bool equalKeys = (priorKeyLength == keyLength); for (UCHAR *p = node.key, *q = key + node.offset, *end = key + l; q < end; p++, q++) { @@ -790,8 +784,6 @@ int IndexPage::deleteNode(Dbb * dbb, Ind return 0; } - - void IndexPage::printPage(IndexPage * page, int32 pageNumber, bool inversion) { LogLock logLock; @@ -1143,7 +1135,6 @@ Bdb* IndexPage::splitIndexPageEnd(Dbb *d int nodeOverhead = 3 + (offset >= 128) + (insertKey->keyLength - offset >= 128); char *nextNextNode = (char*) node.nextNode - node.length + insertKey->keyLength - offset + nodeOverhead; - Btn *splitPos; if (nextNextNode >= (char*) this + dbb->pageSize) { @@ -1408,7 +1399,6 @@ Btn* IndexPage::getEnd(void) { return (Btn*) ((UCHAR*) this + length); } - /* During node insertion, check whether supernode should be added at insertion point */ bool IndexPage::checkAddSuperNode(int pageSize, IndexNode* node, IndexKey *indexKey, int recordNumber, int offset) diff -Nrup a/storage/falcon/IndexPage.h b/storage/falcon/IndexPage.h --- a/storage/falcon/IndexPage.h 2008-03-20 15:56:50 -05:00 +++ b/storage/falcon/IndexPage.h 2008-03-24 22:54:39 -05:00 @@ -77,7 +77,6 @@ public: static int32 getRecordNumber(const UCHAR *ptr); static void logIndexPage (Bdb *bdb, TransId transId); - int32 parentPage; int32 priorPage; int32 nextPage; diff -Nrup a/storage/falcon/IndexRootPage.cpp b/storage/falcon/IndexRootPage.cpp --- a/storage/falcon/IndexRootPage.cpp 2008-03-19 18:46:00 -05:00 +++ b/storage/falcon/IndexRootPage.cpp 2008-03-24 22:54:41 -05:00 @@ -818,7 +818,6 @@ void IndexRootPage::redoIndexPage(Dbb* d memset(indexPage->superNodes, 0, sizeof(indexPage->superNodes)); } - // If we have a parent page, propogate the first node upward if (parentPage && indexPage->priorPage != 0) diff -Nrup a/storage/falcon/Section.cpp b/storage/falcon/Section.cpp --- a/storage/falcon/Section.cpp 2008-03-12 07:15:13 -05:00 +++ b/storage/falcon/Section.cpp 2008-03-24 22:54:43 -05:00 @@ -495,12 +495,20 @@ void Section::updateRecord(int32 recordN Log::debug("UpdateRecord %d in section %d/%d\n", recordNumber, sectionId, dbb->tableSpaceId); #endif + // Since different gopher threads are processing different + // committed transations, and a later smaller transaction + // can be proccessed faster than an earlier larger transaction, + // be sure this record update will not wipe out a later change. + + if (!dbb->serialLog->recovering && table && !table->validateUpdate(recordNumber, transId)) + return; + // Do some fancy accounting to avoid premature use of record number. // If the record number has been reserved, don't bother to delete it. if (!stream) reserveRecordNumber(recordNumber); - + // Find section page and slot for record number within section int32 slot = recordNumber / dbb->linesPerPage; @@ -514,13 +522,6 @@ void Section::updateRecord(int32 recordN bdb = dbb->handoffPage (bdb, pageNumber, PAGE_record_locator, Exclusive); BDB_HISTORY(bdb); - if (!dbb->serialLog->recovering && table && !table->validateUpdate(recordNumber, transId)) - { - bdb->release(); - - return; - } - // We've found the section index page. Mark it bdb->mark(transId); diff -Nrup a/storage/falcon/SerialLog.cpp b/storage/falcon/SerialLog.cpp --- a/storage/falcon/SerialLog.cpp 2008-03-12 07:15:13 -05:00 +++ b/storage/falcon/SerialLog.cpp 2008-03-24 22:54:45 -05:00 @@ -611,9 +611,13 @@ void SerialLog::createNewWindow(void) void SerialLog::shutdown() { finishing = true; - + + // Wake up gophers that are not currently doing anything. + // If they are active, they will see the shutdownInProgress flag. + for (Gopher *gopher = gophers; gopher; gopher = gopher->next) - gopher->wakeup(); + if ((gopher->workerThread) && gopher->workerThread->sleeping && !gopher->active) + gopher->wakeup(); // Wait for all gopher threads to exit @@ -705,7 +709,7 @@ void SerialLog::endRecord(void) void SerialLog::wakeup() { for (Gopher *gopher = gophers; gopher; gopher = gopher->next) - if ((gopher->workerThread) && gopher->workerThread->sleeping) + if ((gopher->workerThread) && gopher->workerThread->sleeping && !gopher->active) { gopher->wakeup(); break; diff -Nrup a/storage/falcon/SyncObject.cpp b/storage/falcon/SyncObject.cpp --- a/storage/falcon/SyncObject.cpp 2008-03-11 10:16:31 -05:00 +++ b/storage/falcon/SyncObject.cpp 2008-03-24 22:54:47 -05:00 @@ -352,11 +352,12 @@ void SyncObject::wait(LockType type, Thr thread->lockPending = sync; ++thread->activeLocks; mutex.release(); + bool wakeup = 0; if (timeout) - for (;;) + while (!thread->lockGranted) { - thread->sleep (timeout); + wakeup = thread->sleep (timeout); if (thread->lockGranted) return; @@ -379,13 +380,14 @@ void SyncObject::wait(LockType type, Thr } mutex.unlock(); - timedout(timeout); + if (!wakeup) + timedout(timeout); } while (!thread->lockGranted) { - bool wakeup = thread->sleep (10000); + wakeup = thread->sleep (10000); if (thread->lockGranted) { diff -Nrup a/storage/falcon/Table.cpp b/storage/falcon/Table.cpp --- a/storage/falcon/Table.cpp 2008-03-12 07:15:13 -05:00 +++ b/storage/falcon/Table.cpp 2008-03-24 22:54:48 -05:00 @@ -346,7 +346,6 @@ void Table::insert(Transaction *transact // Make insert/update atomic, then check for unique index duplicats - Sync sync(&syncUpdate, "Table::insert"); recordNumber = record->recordNumber = dbb->insertStub(dataSection, transaction); if (indexes) @@ -837,7 +836,6 @@ void Table::init(int id, const char *sch syncObject.setName("Table::syncObject"); syncTriggers.setName("Table::syncTriggers"); syncScavenge.setName("Table::syncScavenge"); - syncUpdate.setName("Table::syncUpdate"); syncAlter.setName("Table::syncAlter"); } @@ -2942,8 +2940,6 @@ uint Table::insert(Transaction *transact // Make insert/update atomic, then check for unique index duplicats - Sync sync(&syncUpdate, "Table::insert"); - if (indexes) { checkUniqueIndexes(transaction, record); diff -Nrup a/storage/falcon/Table.h b/storage/falcon/Table.h --- a/storage/falcon/Table.h 2008-03-12 07:15:13 -05:00 +++ b/storage/falcon/Table.h 2008-03-24 22:54:50 -05:00 @@ -219,7 +219,6 @@ public: SyncObject syncObject; SyncObject syncTriggers; SyncObject syncScavenge; - SyncObject syncUpdate; SyncObject syncAlter; // prevent concurrent Alter statements. Table *collision; // Hash collision in database Table *idCollision; // mod(id) collision in database