From 39e750d949b203e2ebd282ac9e6ff3145761b5cf Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Tue, 12 Apr 2005 17:54:34 +0200 Subject: [PATCH 01/47] bug#9749 - ndb lock upgrade handle more cases... --- ndb/src/kernel/blocks/dbacc/Dbacc.hpp | 2 + ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 143 +++++++++++++++++++++- ndb/test/ndbapi/testOperations.cpp | 72 +++++++++-- 3 files changed, 204 insertions(+), 13 deletions(-) diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp index 64b947b5462..aaa4aca7b00 100644 --- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp +++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp @@ -1100,6 +1100,8 @@ private: Uint32 executeNextOperation(Signal* signal); void releaselock(Signal* signal); void takeOutFragWaitQue(Signal* signal); + void check_lock_upgrade(Signal* signal, OperationrecPtr lock_owner, + OperationrecPtr release_op); void allocOverflowPage(Signal* signal); bool getrootfragmentrec(Signal* signal, RootfragmentrecPtr&, Uint32 fragId); void insertLockOwnersList(Signal* signal, const OperationrecPtr&); diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 17c5a31cbed..28956de198c 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -5802,9 +5802,148 @@ void Dbacc::commitOperation(Signal* signal) ptrCheckGuard(tolqTmpPtr, coprecsize, operationrec); tolqTmpPtr.p->prevParallelQue = operationRecPtr.p->prevParallelQue; }//if - }//if + + /** + * Check possible lock upgrade + * 1) Find lock owner + * 2) Count transactions in parallel que + * 3) If count == 1 and TRANSID(next serial) == TRANSID(lock owner) + * upgrade next serial + */ + if(operationRecPtr.p->lockMode) + { + jam(); + /** + * Committing a non shared operation can't lead to lock upgrade + */ + return; + } + + OperationrecPtr lock_owner; + lock_owner.i = operationRecPtr.p->prevParallelQue; + ptrCheckGuard(lock_owner, coprecsize, operationrec); + Uint32 transid[2] = { lock_owner.p->transId1, + lock_owner.p->transId2 }; + + + while(lock_owner.p->prevParallelQue != RNIL) + { + lock_owner.i = lock_owner.p->prevParallelQue; + ptrCheckGuard(lock_owner, coprecsize, operationrec); + + if(lock_owner.p->transId1 != transid[0] || + lock_owner.p->transId2 != transid[1]) + { + jam(); + /** + * If more than 1 trans in lock queue -> no lock upgrade + */ + return; + } + } + + check_lock_upgrade(signal, lock_owner, operationRecPtr); + } }//Dbacc::commitOperation() +void +Dbacc::check_lock_upgrade(Signal* signal, + OperationrecPtr lock_owner, + OperationrecPtr release_op) +{ + if((lock_owner.p->transId1 == release_op.p->transId1 && + lock_owner.p->transId2 == release_op.p->transId2) || + release_op.p->lockMode || + lock_owner.p->nextSerialQue == RNIL) + { + jam(); + /** + * No lock upgrade if same trans or lock owner has no serial queue + * or releasing non shared op + */ + return; + } + + OperationrecPtr next; + next.i = lock_owner.p->nextSerialQue; + ptrCheckGuard(next, coprecsize, operationrec); + + if(lock_owner.p->transId1 != next.p->transId1 || + lock_owner.p->transId2 != next.p->transId2) + { + jam(); + /** + * No lock upgrad if !same trans in serial queue + */ + return; + } + + tgnptMainOpPtr = lock_owner; + getNoParallelTransaction(signal); + if (tgnptNrTransaction > 1) + { + jam(); + /** + * No lock upgrade if more than 1 transaction in parallell queue + */ + return; + } + + OperationrecPtr tmp; + tmp.i = lock_owner.p->nextSerialQue = next.p->nextSerialQue; + if(tmp.i != RNIL) + { + ptrCheckGuard(tmp, coprecsize, operationrec); + ndbassert(tmp.p->prevSerialQue == next.i); + tmp.p->prevSerialQue = lock_owner.i; + } + next.p->nextSerialQue = next.p->prevSerialQue = RNIL; + + // Find end of parallell que + tmp = lock_owner; + tmp.p->lockMode= 1; + while(tmp.p->nextParallelQue != RNIL) + { + jam(); + tmp.i = tmp.p->nextParallelQue; + ptrCheckGuard(tmp, coprecsize, operationrec); + tmp.p->lockMode= 1; + } + + next.p->prevParallelQue = tmp.i; + tmp.p->nextParallelQue = next.i; + + OperationrecPtr save = operationRecPtr; + + Uint32 TelementIsDisappeared = 0; // lock upgrade = all reads + Uint32 ThashValue = lock_owner.p->hashValue; + Uint32 localdata[2]; + localdata[0] = lock_owner.p->localdata[0]; + localdata[1] = lock_owner.p->localdata[1]; + do { + next.p->elementIsDisappeared = TelementIsDisappeared; + next.p->hashValue = ThashValue; + next.p->localdata[0] = localdata[0]; + next.p->localdata[1] = localdata[1]; + + operationRecPtr = next; + ndbassert(next.p->lockMode); + TelementIsDisappeared = executeNextOperation(signal); + if (next.p->nextParallelQue != RNIL) + { + jam(); + next.i = next.p->nextParallelQue; + ptrCheckGuard(next, coprecsize, operationrec); + } else { + jam(); + break; + }//if + } while (1); + + operationRecPtr = save; + +} + /* ------------------------------------------------------------------------- */ /* RELEASELOCK */ /* RESETS LOCK OF AN ELEMENT. */ @@ -5841,6 +5980,8 @@ void Dbacc::releaselock(Signal* signal) ptrCheckGuard(trlTmpOperPtr, coprecsize, operationrec); trlTmpOperPtr.p->prevSerialQue = trlOperPtr.i; }//if + + check_lock_upgrade(signal, copyInOperPtr, operationRecPtr); /* --------------------------------------------------------------------------------- */ /* SINCE THERE ARE STILL ITEMS IN THE PARALLEL QUEUE WE NEED NOT WORRY ABOUT */ /* STARTING QUEUED OPERATIONS. THUS WE CAN END HERE. */ diff --git a/ndb/test/ndbapi/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp index 9f1d5ee1191..773511a0475 100644 --- a/ndb/test/ndbapi/testOperations.cpp +++ b/ndb/test/ndbapi/testOperations.cpp @@ -547,21 +547,64 @@ runLockUpgrade1(NDBT_Context* ctx, NDBT_Step* step){ do { CHECK(hugoOps.startTransaction(pNdb) == 0); - CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0); - CHECK(hugoOps.execute_NoCommit(pNdb) == 0); + if(ctx->getProperty("LOCK_UPGRADE", 1) == 1) + { + CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0); + CHECK(hugoOps.execute_NoCommit(pNdb) == 0); - ctx->setProperty("READ_DONE", 1); - ctx->broadcast(); - ndbout_c("wait 2"); - ctx->getPropertyWait("READ_DONE", 2); - ndbout_c("wait 2 - done"); + ctx->setProperty("READ_DONE", 1); + ctx->broadcast(); + ndbout_c("wait 2"); + ctx->getPropertyWait("READ_DONE", 2); + ndbout_c("wait 2 - done"); + } + else + { + ctx->setProperty("READ_DONE", 1); + ctx->broadcast(); + ctx->getPropertyWait("READ_DONE", 2); + ndbout_c("wait 2 - done"); + CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0); + CHECK(hugoOps.execute_NoCommit(pNdb) == 0); + } + if(ctx->getProperty("LU_OP", o_INS) == o_INS) + { + CHECK(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + CHECK(hugoOps.pkInsertRecord(pNdb, 0, 1, 2) == 0); + } + else if(ctx->getProperty("LU_OP", o_UPD) == o_UPD) + { + CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, 2) == 0); + } + else + { + CHECK(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + } ctx->setProperty("READ_DONE", 3); ctx->broadcast(); ndbout_c("before update"); - CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, 2) == 0); ndbout_c("wait update"); - CHECK(hugoOps.execute_NoCommit(pNdb) == 0); - CHECK(hugoOps.closeTransaction(pNdb)); + CHECK(hugoOps.execute_Commit(pNdb) == 0); + CHECK(hugoOps.closeTransaction(pNdb) == 0); + + CHECK(hugoOps.startTransaction(pNdb) == 0); + CHECK(hugoOps.pkReadRecord(pNdb, 0, 1) == 0); + int res= hugoOps.execute_Commit(pNdb); + if(ctx->getProperty("LU_OP", o_INS) == o_INS) + { + CHECK(res == 0); + CHECK(hugoOps.verifyUpdatesValue(2) == 0); + } + else if(ctx->getProperty("LU_OP", o_UPD) == o_UPD) + { + CHECK(res == 0); + CHECK(hugoOps.verifyUpdatesValue(2) == 0); + } + else + { + CHECK(res == 626); + } + } while(0); return result; @@ -592,10 +635,10 @@ runLockUpgrade2(NDBT_Context* ctx, NDBT_Step* step){ ndbout_c("wait 3 - done"); NdbSleep_MilliSleep(200); - CHECK(hugoOps.execute_Commit(pNdb) == 0); + CHECK(hugoOps.execute_Commit(pNdb) == 0); } while(0); - return NDBT_FAILED; + return result; } int @@ -607,11 +650,16 @@ main(int argc, const char** argv){ NDBT_TestSuite ts("testOperations"); + for(Uint32 i = 0; i <6; i++) { BaseString name("bug_9749"); + name.appfmt("_%d", i); NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts, name.c_str(), ""); + pt->setProperty("LOCK_UPGRADE", 1 + (i & 1)); + pt->setProperty("LU_OP", 1 + (i >> 1)); + pt->addInitializer(new NDBT_Initializer(pt, "runClearTable", runClearTable)); From 45a07db5c01937b37c4d62b7bdcd024740d87e6d Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Wed, 13 Apr 2005 09:54:40 +0200 Subject: [PATCH 02/47] BUG#9749 - ndb lock upgrade - more fixes... 1) Make getNoParall into function instead of a procedure 2) Check for multiple transactions in "upgrade's" parallell queue 3) Set lock mode according to lock_owner's lockMode NOTE: Does still not handle lock upgrade in case of aborts correctly --- ndb/src/kernel/blocks/dbacc/Dbacc.hpp | 4 +- ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 69 +++++++++++------------ 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp index aaa4aca7b00..246afc5ceb8 100644 --- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp +++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp @@ -1022,7 +1022,7 @@ private: Uint32 placeReadInLockQueue(Signal* signal); void placeSerialQueueRead(Signal* signal); void checkOnlyReadEntry(Signal* signal); - void getNoParallelTransaction(Signal* signal); + Uint32 getNoParallelTransaction(const Operationrec*); void moveLastParallelQueue(Signal* signal); void moveLastParallelQueueWrite(Signal* signal); Uint32 placeWriteInLockQueue(Signal* signal); @@ -1265,7 +1265,6 @@ private: OperationrecPtr mlpqOperPtr; OperationrecPtr queOperPtr; OperationrecPtr readWriteOpPtr; - OperationrecPtr tgnptMainOpPtr; Uint32 cfreeopRec; Uint32 coprecsize; /* --------------------------------------------------------------------------------- */ @@ -1516,7 +1515,6 @@ private: Uint32 turlIndex; Uint32 tlfrTmp1; Uint32 tlfrTmp2; - Uint32 tgnptNrTransaction; Uint32 tudqeIndex; Uint32 tscanTrid1; Uint32 tscanTrid2; diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 28956de198c..cdb9091da42 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -1936,9 +1936,7 @@ void Dbacc::insertelementLab(Signal* signal) /* --------------------------------------------------------------------------------- */ Uint32 Dbacc::placeReadInLockQueue(Signal* signal) { - tgnptMainOpPtr = queOperPtr; - getNoParallelTransaction(signal); - if (tgnptNrTransaction == 1) { + if (getNoParallelTransaction(queOperPtr.p) == 1) { if ((queOperPtr.p->transId1 == operationRecPtr.p->transId1) && (queOperPtr.p->transId2 == operationRecPtr.p->transId2)) { /* --------------------------------------------------------------------------------- */ @@ -2021,9 +2019,7 @@ void Dbacc::placeSerialQueueRead(Signal* signal) checkOnlyReadEntry(signal); return; }//if - tgnptMainOpPtr = readWriteOpPtr; - getNoParallelTransaction(signal); - if (tgnptNrTransaction == 1) { + if (getNoParallelTransaction(readWriteOpPtr.p) == 1) { jam(); /* --------------------------------------------------------------------------------- */ /* THERE WAS ONLY ONE TRANSACTION INVOLVED IN THE PARALLEL QUEUE. IF THIS IS OUR */ @@ -2104,24 +2100,23 @@ void Dbacc::checkOnlyReadEntry(Signal* signal) /* --------------------------------------------------------------------------------- */ /* GET_NO_PARALLEL_TRANSACTION */ /* --------------------------------------------------------------------------------- */ -void Dbacc::getNoParallelTransaction(Signal* signal) +Uint32 +Dbacc::getNoParallelTransaction(const Operationrec * op) { - OperationrecPtr tnptOpPtr; - - tgnptNrTransaction = 1; - tnptOpPtr.i = tgnptMainOpPtr.p->nextParallelQue; - while ((tnptOpPtr.i != RNIL) && - (tgnptNrTransaction == 1)) { + OperationrecPtr tmp; + + tmp.i= op->nextParallelQue; + Uint32 transId[2] = { op->transId1, op->transId2 }; + while (tmp.i != RNIL) + { jam(); - ptrCheckGuard(tnptOpPtr, coprecsize, operationrec); - if ((tnptOpPtr.p->transId1 == tgnptMainOpPtr.p->transId1) && - (tnptOpPtr.p->transId2 == tgnptMainOpPtr.p->transId2)) { - tnptOpPtr.i = tnptOpPtr.p->nextParallelQue; - } else { - jam(); - tgnptNrTransaction++; - }//if - }//while + ptrCheckGuard(tmp, coprecsize, operationrec); + if (tmp.p->transId1 == transId[0] && tmp.p->transId2 == transId[1]) + tmp.i = tmp.p->nextParallelQue; + else + return 2; + } + return 1; }//Dbacc::getNoParallelTransaction() void Dbacc::moveLastParallelQueue(Signal* signal) @@ -2162,9 +2157,7 @@ void Dbacc::moveLastParallelQueueWrite(Signal* signal) /* --------------------------------------------------------------------------------- */ Uint32 Dbacc::placeWriteInLockQueue(Signal* signal) { - tgnptMainOpPtr = queOperPtr; - getNoParallelTransaction(signal); - if (!((tgnptNrTransaction == 1) && + if (!((getNoParallelTransaction(queOperPtr.p) == 1) && (queOperPtr.p->transId1 == operationRecPtr.p->transId1) && (queOperPtr.p->transId2 == operationRecPtr.p->transId2))) { jam(); @@ -2215,9 +2208,7 @@ void Dbacc::placeSerialQueueWrite(Signal* signal) }//if readWriteOpPtr.i = readWriteOpPtr.p->nextSerialQue; ptrCheckGuard(readWriteOpPtr, coprecsize, operationrec); - tgnptMainOpPtr = readWriteOpPtr; - getNoParallelTransaction(signal); - if (tgnptNrTransaction == 1) { + if (getNoParallelTransaction(readWriteOpPtr.p) == 1) { /* --------------------------------------------------------------------------------- */ /* THERE WAS ONLY ONE TRANSACTION INVOLVED IN THE PARALLEL QUEUE. IF THIS IS OUR */ /* TRANSACTION WE CAN STILL GET HOLD OF THE LOCK. */ @@ -5878,9 +5869,7 @@ Dbacc::check_lock_upgrade(Signal* signal, return; } - tgnptMainOpPtr = lock_owner; - getNoParallelTransaction(signal); - if (tgnptNrTransaction > 1) + if (getNoParallelTransaction(lock_owner.p) > 1) { jam(); /** @@ -5888,6 +5877,15 @@ Dbacc::check_lock_upgrade(Signal* signal, */ return; } + + if (getNoParallelTransaction(next.p) > 1) + { + jam(); + /** + * No lock upgrade if more than 1 transaction in next's parallell queue + */ + return; + } OperationrecPtr tmp; tmp.i = lock_owner.p->nextSerialQue = next.p->nextSerialQue; @@ -5901,20 +5899,19 @@ Dbacc::check_lock_upgrade(Signal* signal, // Find end of parallell que tmp = lock_owner; - tmp.p->lockMode= 1; while(tmp.p->nextParallelQue != RNIL) { jam(); tmp.i = tmp.p->nextParallelQue; ptrCheckGuard(tmp, coprecsize, operationrec); - tmp.p->lockMode= 1; } next.p->prevParallelQue = tmp.i; tmp.p->nextParallelQue = next.i; OperationrecPtr save = operationRecPtr; - + Uint32 lockMode = lock_owner.p->lockMode; + Uint32 TelementIsDisappeared = 0; // lock upgrade = all reads Uint32 ThashValue = lock_owner.p->hashValue; Uint32 localdata[2]; @@ -5927,7 +5924,7 @@ Dbacc::check_lock_upgrade(Signal* signal, next.p->localdata[1] = localdata[1]; operationRecPtr = next; - ndbassert(next.p->lockMode); + next.p->lockMode = lockMode; TelementIsDisappeared = executeNextOperation(signal); if (next.p->nextParallelQue != RNIL) { @@ -5941,7 +5938,7 @@ Dbacc::check_lock_upgrade(Signal* signal, } while (1); operationRecPtr = save; - + } /* ------------------------------------------------------------------------- */ From 27f7a6c41bb9bd786d16e2b24fce66b16a9d99b5 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Thu, 14 Apr 2005 13:43:07 +0200 Subject: [PATCH 03/47] BUG#9891 - ndb lcp Crash if ACC_CONTOPREQ was sent while ACC_LCPCONF was in job buffer if ACC_LCPCONF would have arrived eariler (before TUP_LCPSTARTED) operations could lockup. But would be restarted on next LCP -- LQH 1) Better check for LCP started that will also return true if ACC or TUP already has completed 2) Remove incorrect if statement that prevented operations to be started if ACC has completed -- ACC Make sure all ACC_CONTOPCONF are sent before releasing lcp record i.e. use noOfLcpConf == 4 (2 ACC_LCPCONF + 2 ACC_CONTOPCONF) Check for == 4 also when sending ACC_CONTOPCONF --- ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 20 ++++++- ndb/src/kernel/blocks/dblqh/Dblqh.hpp | 3 +- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 66 +++++++++-------------- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index cdb9091da42..d566639489c 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -8486,7 +8486,7 @@ void Dbacc::checkSendLcpConfLab(Signal* signal) break; }//switch lcpConnectptr.p->noOfLcpConf++; - ndbrequire(lcpConnectptr.p->noOfLcpConf <= 2); + ndbrequire(lcpConnectptr.p->noOfLcpConf <= 4); fragrecptr.p->fragState = ACTIVEFRAG; rlpPageptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(rlpPageptr, cpagesize, page8); @@ -8504,7 +8504,7 @@ void Dbacc::checkSendLcpConfLab(Signal* signal) }//for signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPCONF, signal, 1, JBB); - if (lcpConnectptr.p->noOfLcpConf == 2) { + if (lcpConnectptr.p->noOfLcpConf == 4) { jam(); releaseLcpConnectRec(signal); rootfragrecptr.i = fragrecptr.p->myroot; @@ -8535,6 +8535,13 @@ void Dbacc::execACC_CONTOPREQ(Signal* signal) /* LOCAL FRAG ID */ tresult = 0; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); + if(ERROR_INSERTED(3002) && lcpConnectptr.p->noOfLcpConf < 2) + { + sendSignalWithDelay(cownBlockref, GSN_ACC_CONTOPREQ, signal, 300, + signal->getLength()); + return; + } + ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); rootfragrecptr.i = lcpConnectptr.p->rootrecptr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); @@ -8568,6 +8575,15 @@ void Dbacc::execACC_CONTOPREQ(Signal* signal) }//while signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_CONTOPCONF, signal, 1, JBA); + + lcpConnectptr.p->noOfLcpConf++; + if (lcpConnectptr.p->noOfLcpConf == 4) { + jam(); + releaseLcpConnectRec(signal); + rootfragrecptr.i = fragrecptr.p->myroot; + ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); + rootfragrecptr.p->rootState = ACTIVEROOT; + }//if return; /* ALL QUEUED OPERATION ARE RESTARTED IF NEEDED. */ }//Dbacc::execACC_CONTOPREQ() diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 0c63cb5fe17..19e055a3011 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -968,7 +968,6 @@ public: enum LcpState { LCP_IDLE = 0, - LCP_STARTED = 1, LCP_COMPLETED = 2, LCP_WAIT_FRAGID = 3, LCP_WAIT_TUP_PREPLCP = 4, @@ -2266,7 +2265,7 @@ private: void sendCopyActiveConf(Signal* signal,Uint32 tableId); void checkLcpCompleted(Signal* signal); void checkLcpHoldop(Signal* signal); - void checkLcpStarted(Signal* signal); + bool checkLcpStarted(Signal* signal); void checkLcpTupprep(Signal* signal); void getNextFragForLcp(Signal* signal); void initLcpLocAcc(Signal* signal, Uint32 fragId); diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index c79f4dfc6c7..27f995750b6 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -10351,8 +10351,8 @@ void Dblqh::execTUP_LCPSTARTED(Signal* signal) void Dblqh::lcpStartedLab(Signal* signal) { - checkLcpStarted(signal); - if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) { + if (checkLcpStarted(signal)) + { jam(); /* ---------------------------------------------------------------------- * THE LOCAL CHECKPOINT HAS BEEN STARTED. IT IS NOW TIME TO @@ -10432,26 +10432,7 @@ void Dblqh::execLQH_RESTART_OP(Signal* signal) lcpPtr.i = signal->theData[1]; ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord); ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED); - if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) { - jam(); - /***********************************************************************/ - /* THIS SIGNAL CAN ONLY BE RECEIVED WHEN FRAGMENT IS BLOCKED AND - * THE LOCAL CHECKPOINT HAS BEEN STARTED. THE BLOCKING WILL BE - * REMOVED AS SOON AS ALL OPERATIONS HAVE BEEN STARTED. - ***********************************************************************/ - restartOperationsLab(signal); - } else if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) { - jam(); - /*******************************************************************> - * THE CHECKPOINT IS COMPLETED BUT HAS NOT YET STARTED UP - * ALL OPERATIONS AGAIN. - * WE PERFORM THIS START-UP BEFORE CONTINUING WITH THE NEXT - * FRAGMENT OF THE LOCAL CHECKPOINT TO AVOID ANY STRANGE ERRORS. - *******************************************************************> */ - restartOperationsLab(signal); - } else { - ndbrequire(false); - } + restartOperationsLab(signal); }//Dblqh::execLQH_RESTART_OP() void Dblqh::restartOperationsLab(Signal* signal) @@ -11000,7 +10981,8 @@ void Dblqh::checkLcpHoldop(Signal* signal) * * SUBROUTINE SHORT NAME = CLS * ========================================================================== */ -void Dblqh::checkLcpStarted(Signal* signal) +bool +Dblqh::checkLcpStarted(Signal* signal) { LcpLocRecordPtr clsLcpLocptr; @@ -11010,7 +10992,7 @@ void Dblqh::checkLcpStarted(Signal* signal) do { ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord); if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED){ - return; + return false; }//if clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc; i++; @@ -11021,12 +11003,13 @@ void Dblqh::checkLcpStarted(Signal* signal) do { ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord); if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED){ - return; + return false; }//if clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc; i++; } while (clsLcpLocptr.i != RNIL); - lcpPtr.p->lcpState = LcpRecord::LCP_STARTED; + + return true; }//Dblqh::checkLcpStarted() /* ========================================================================== @@ -11187,20 +11170,12 @@ void Dblqh::sendAccContOp(Signal* signal) do { ptrCheckGuard(sacLcpLocptr, clcpLocrecFileSize, lcpLocRecord); sacLcpLocptr.p->accContCounter = 0; - if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_STARTED){ - /* ------------------------------------------------------------------- */ - /*SEND START OPERATIONS TO ACC AGAIN */ - /* ------------------------------------------------------------------- */ - signal->theData[0] = lcpPtr.p->lcpAccptr; - signal->theData[1] = sacLcpLocptr.p->locFragid; - sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA); - count++; - } else if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_COMPLETED){ - signal->theData[0] = sacLcpLocptr.i; - sendSignal(reference(), GSN_ACC_CONTOPCONF, signal, 1, JBB); - } else { - ndbrequire(false); - } + /* ------------------------------------------------------------------- */ + /*SEND START OPERATIONS TO ACC AGAIN */ + /* ------------------------------------------------------------------- */ + signal->theData[0] = lcpPtr.p->lcpAccptr; + signal->theData[1] = sacLcpLocptr.p->locFragid; + sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA); sacLcpLocptr.i = sacLcpLocptr.p->nextLcpLoc; } while (sacLcpLocptr.i != RNIL); @@ -11236,9 +11211,18 @@ void Dblqh::sendStartLcp(Signal* signal) signal->theData[0] = stlLcpLocptr.i; signal->theData[1] = cownref; signal->theData[2] = stlLcpLocptr.p->tupRef; - sendSignal(fragptr.p->tupBlockref, GSN_TUP_LCPREQ, signal, 3, JBA); + if(ERROR_INSERTED(5077)) + sendSignalWithDelay(fragptr.p->tupBlockref, GSN_TUP_LCPREQ, + signal, 5000, 3); + else + sendSignal(fragptr.p->tupBlockref, GSN_TUP_LCPREQ, signal, 3, JBA); stlLcpLocptr.i = stlLcpLocptr.p->nextLcpLoc; } while (stlLcpLocptr.i != RNIL); + + if(ERROR_INSERTED(5077)) + { + ndbout_c("Delayed TUP_LCPREQ with 5 sec"); + } }//Dblqh::sendStartLcp() /* ------------------------------------------------------------------------- */ From f931466f36c0038181c897e6a6e70d046e9d216e Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Mon, 18 Apr 2005 12:41:12 +0200 Subject: [PATCH 04/47] bug#9892 Make BUILDINDX RF_LOCAL aware --- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 37 +++++++++++++++++++------ ndb/src/ndbapi/Ndbif.cpp | 10 +++---- ndb/test/ndbapi/testIndex.cpp | 2 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 7247b7e2b9c..184db794057 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -9811,11 +9811,20 @@ Dbdict::execBUILDINDXREQ(Signal* signal) requestType == BuildIndxReq::RT_ALTER_INDEX || requestType == BuildIndxReq::RT_SYSTEMRESTART) { jam(); + + const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL; + NdbNodeBitmask receiverNodes = c_aliveNodes; + if (isLocal) { + receiverNodes.clear(); + receiverNodes.set(getOwnNodeId()); + } + if (signal->getLength() == BuildIndxReq::SignalLength) { jam(); - if (getOwnNodeId() != c_masterNodeId) { + + if (!isLocal && getOwnNodeId() != c_masterNodeId) { jam(); - + releaseSections(signal); OpBuildIndex opBad; opPtr.p = &opBad; @@ -9828,9 +9837,9 @@ Dbdict::execBUILDINDXREQ(Signal* signal) } // forward initial request plus operation key to all req->setOpKey(++c_opRecordSequence); - NodeReceiverGroup rg(DBDICT, c_aliveNodes); + NodeReceiverGroup rg(DBDICT, receiverNodes); sendSignal(rg, GSN_BUILDINDXREQ, - signal, BuildIndxReq::SignalLength + 1, JBB); + signal, BuildIndxReq::SignalLength + 1, JBB); return; } // seize operation record @@ -9853,7 +9862,7 @@ Dbdict::execBUILDINDXREQ(Signal* signal) } c_opBuildIndex.add(opPtr); // master expects to hear from all - opPtr.p->m_signalCounter = c_aliveNodes; + opPtr.p->m_signalCounter = receiverNodes; buildIndex_sendReply(signal, opPtr, false); return; } @@ -10208,10 +10217,20 @@ Dbdict::buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr) req->setConnectionPtr(opPtr.p->key); req->setRequestType(opPtr.p->m_requestType); req->addRequestFlag(opPtr.p->m_requestFlag); - opPtr.p->m_signalCounter = c_aliveNodes; - NodeReceiverGroup rg(DBDICT, c_aliveNodes); - sendSignal(rg, GSN_BUILDINDXREQ, - signal, BuildIndxReq::SignalLength, JBB); + if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) + { + opPtr.p->m_signalCounter.clearWaitingFor(); + opPtr.p->m_signalCounter.setWaitingFor(getOwnNodeId()); + sendSignal(reference(), GSN_BUILDINDXREQ, + signal, BuildIndxReq::SignalLength, JBB); + } + else + { + opPtr.p->m_signalCounter = c_aliveNodes; + NodeReceiverGroup rg(DBDICT, c_aliveNodes); + sendSignal(rg, GSN_BUILDINDXREQ, + signal, BuildIndxReq::SignalLength, JBB); + } } void diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index a4f233709c4..1caebe436ef 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -453,7 +453,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tFirstDataPtr = int2void(tFirstData); if(tFirstDataPtr != 0){ tOp = void2rec_op(tFirstDataPtr); - if (tOp->checkMagicNumber() == 0) { + if (tOp->checkMagicNumber(false) == 0) { tCon = tOp->theNdbCon; if (tCon != NULL) { if ((tCon->theSendStatus == NdbConnection::sendTC_OP) || @@ -466,11 +466,11 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) }//if }//if }//if - } else { -#ifdef VM_TRACE - ndbout_c("Recevied TCKEY_FAILREF wo/ operation"); -#endif } +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILREF wo/ operation"); +#endif + return; break; } case GSN_TCKEYREF: diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index 6623ad35a7f..d359f83257f 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -1329,7 +1329,7 @@ TESTCASE("NFNR2_O", INITIALIZER(runLoadTable); STEP(runRestarts); STEP(runTransactions2); - STEP(runTransactions2); + //STEP(runTransactions2); FINALIZER(runVerifyIndex); FINALIZER(createRandomIndex_Drop); FINALIZER(createPkIndex_Drop); From c0248b218688f81ccc4540278bfb01266f8dd875 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Mon, 18 Apr 2005 12:46:35 +0200 Subject: [PATCH 05/47] bug#9892 - ndb index activation 4.1->5.0 merge fix --- ndb/test/ndbapi/testIndex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index bb3c41d0474..5785db232c4 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -1323,7 +1323,7 @@ TESTCASE("NFNR2_O", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("OrderedIndex", 1); TC_PROPERTY("LoggedIndexes", (unsigned)0); - TC_PROPERTY("PauseThreads", 2); + TC_PROPERTY("PauseThreads", 1); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); From 8974ce0836c79d6faa137f334de3b56abc6499af Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 20 Apr 2005 19:27:46 +0300 Subject: [PATCH 06/47] Many files: Semi-synchronous replication for InnoDB type tables; before telling the client that a commit has been processed, wait that the replication thread has returned from my_net_send() where it sends the binlog to the slave; note that TCP/IP, even with the TCP_NODELAY option does not guarantee that the slave has RECEIVED the data - this is just heuristic at the moment; this is useful in failover: in almost all cases, every transaction that has returned from the commit has been sent and processed in the slave, which makes failover to the slave simpler if the master crashes; the code does not work yet as is, because MySQL should call innobase_report_binlog_offset_and_commit() in a commit; we will most probably return that call to 5.0.x, to make InnoDB Hot Backup and group commit to work again; XA code broke them temporarily in 5.0.3 --- sql/ha_innodb.cc | 287 ++++++++++++++++++++++++++++++++++++++++++++++- sql/ha_innodb.h | 2 + sql/handler.cc | 57 ++++++++++ sql/handler.h | 6 +- sql/mysqld.cc | 2 - sql/set_var.cc | 2 - sql/sql_repl.cc | 37 ++++++ 7 files changed, 382 insertions(+), 11 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3f592e36219..e68a85bdac9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -45,10 +45,58 @@ have disables the InnoDB inlining in this file. */ #include "ha_innodb.h" -pthread_mutex_t innobase_share_mutex, // to protect innobase_open_files - prepare_commit_mutex; // to force correct commit order in binlog +pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ + prepare_commit_mutex; /* to force correct commit order in + binlog */ bool innodb_inited= 0; +/*-----------------------------------------------------------------*/ +/* These variables are used to implement (semi-)synchronous MySQL binlog +replication for InnoDB tables. */ + +pthread_cond_t innobase_repl_cond; /* Posix cond variable; + this variable is signaled + when enough binlog has been + sent to slave, so that a + waiting trx can return the + 'ok' message to the client + for a commit */ +pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex + that also protects the next + innobase_repl_... variables */ +uint innobase_repl_state; /* 1 if synchronous replication + is switched on and is working + ok; else 0 */ +uint innobase_repl_file_name_inited = 0; /* This is set to 1 when + innobase_repl_file_name + contains meaningful data */ +char* innobase_repl_file_name; /* The binlog name up to which + we have sent some binlog to + the slave */ +my_off_t innobase_repl_pos; /* The position in that file + up to which we have sent the + binlog to the slave */ +uint innobase_repl_n_wait_threads = 0; /* This tells how many + transactions currently are + waiting for the binlog to be + sent to the client */ +uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1 + when we know the 'smallest' + wait position */ +char* innobase_repl_wait_file_name; /* NULL, or the 'smallest' + innobase_repl_file_name that + a transaction is waiting for */ +my_off_t innobase_repl_wait_pos; /* The smallest position in + that file that a trx is + waiting for: the trx can + proceed and send an 'ok' to + the client when MySQL has sent + the binlog up to this position + to the slave */ +/*-----------------------------------------------------------------*/ + + + /* Store MySQL definition of 'byte': in Linux it is char while InnoDB uses unsigned char; the header univ.i which we include next defines 'byte' as a macro which expands to 'unsigned char' */ @@ -97,7 +145,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, innobase_log_file_size, innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb, innobase_buffer_pool_size, innobase_additional_mem_pool_size, - innobase_file_io_threads, innobase_lock_wait_timeout, + innobase_file_io_threads, innobase_lock_wait_timeout, innobase_thread_concurrency, innobase_force_recovery, innobase_open_files; @@ -1531,10 +1579,10 @@ innobase_commit( DBUG_RETURN(0); } -/* The following defined-out code will be enabled later when we put the +/* TODO: put the MySQL-4.1 functionality back to 5.0. This is needed to get InnoDB Hot Backup to work. */ -#if 0 + /********************************************************************* This is called when MySQL writes the binlog entry for the current transaction. Writes to the InnoDB tablespace info which tells where the @@ -1563,6 +1611,24 @@ innobase_report_binlog_offset_and_commit( trx->mysql_log_file_name = log_file_name; trx->mysql_log_offset = (ib_longlong)end_offset; + if (thd->variables.sync_replication) { + /* Let us store the binlog file name and the position, so that + we know how long to wait for the binlog to the replicated to + the slave in synchronous replication. */ + + if (trx->repl_wait_binlog_name == NULL) { + + trx->repl_wait_binlog_name = + (char*)mem_alloc(FN_REFLEN + 100); + } + + ut_a(strlen(log_file_name) <= FN_REFLEN + 100); + + strcpy(trx->repl_wait_binlog_name, log_file_name); + + trx->repl_wait_binlog_pos = (ib_longlong)end_offset; + } + trx->flush_log_later = TRUE; innobase_commit(thd, trx_handle); @@ -1572,6 +1638,7 @@ innobase_report_binlog_offset_and_commit( return(0); } +#if 0 /*********************************************************************** This function stores the binlog offset and flushes logs. */ @@ -1602,7 +1669,6 @@ innobase_store_binlog_offset_and_flush_log( /* Syncronous flush of the log buffer to disk */ log_buffer_flush_to_disk(); } - #endif /********************************************************************* @@ -1615,7 +1681,10 @@ innobase_commit_complete( /* out: 0 */ THD* thd) /* in: user thread */ { + struct timespec abstime; trx_t* trx; + int cmp; + int ret; trx = (trx_t*) thd->ha_data[innobase_hton.slot]; @@ -1631,9 +1700,215 @@ innobase_commit_complete( trx_commit_complete_for_mysql(trx); } + printf("Wait binlog name %s, repl state %lu\n", + trx->repl_wait_binlog_name, + (uint)innobase_repl_state); + + if (thd->variables.sync_replication + && trx->repl_wait_binlog_name + && innobase_repl_state != 0) { + + /* In synchronous replication, let us wait until the MySQL + replication has sent the relevant binlog segment to the + replication slave. */ + +/* TODO: Make sure MySQL uses some way (TCP_NODELAY?) to ensure that the data +has been received in the slave! */ + + pthread_mutex_lock(&innobase_repl_cond_mutex); +try_again: + if (innobase_repl_state == 0) { + + pthread_mutex_unlock(&innobase_repl_cond_mutex); + + return(0); + } + + cmp = strcmp(innobase_repl_file_name, + trx->repl_wait_binlog_name); + if (cmp > 0 + || (cmp == 0 && innobase_repl_pos + >= (my_off_t)trx->repl_wait_binlog_pos)) { + /* We have already sent the relevant binlog to the + slave: no need to wait here */ + + pthread_mutex_unlock(&innobase_repl_cond_mutex); + +/* printf("Binlog now sent\n"); */ + + return(0); + } + + /* Let us update the info about the minimum binlog position + of waiting threads in the innobase_repl_... variables */ + + if (innobase_repl_wait_file_name_inited != 0) { + cmp = strcmp(trx->repl_wait_binlog_name, + innobase_repl_wait_file_name); + if (cmp < 0 + || (cmp == 0 && (my_off_t)trx->repl_wait_binlog_pos + <= innobase_repl_wait_pos)) { + /* This thd has an even lower position, let + us update the minimum info */ + + strcpy(innobase_repl_wait_file_name, + trx->repl_wait_binlog_name); + + innobase_repl_wait_pos = + trx->repl_wait_binlog_pos; + } + } else { + strcpy(innobase_repl_wait_file_name, + trx->repl_wait_binlog_name); + + innobase_repl_wait_pos = trx->repl_wait_binlog_pos; + + innobase_repl_wait_file_name_inited = 1; + } + set_timespec(abstime, thd->variables.sync_replication_timeout); + + /* Let us suspend this thread to wait on the condition; + when replication has progressed far enough, we will release + these waiting threads. The following call + pthread_cond_timedwait also atomically unlocks + innobase_repl_cond_mutex. */ + + innobase_repl_n_wait_threads++; + +/* printf("Waiting for binlog to be sent\n"); */ + + ret = pthread_cond_timedwait(&innobase_repl_cond, + &innobase_repl_cond_mutex, &abstime); + innobase_repl_n_wait_threads--; + + if (ret != 0) { + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error: MySQL synchronous replication\n" +"InnoDB: was not able to send the binlog to the slave within the\n" +"InnoDB: timeout %lu. We assume that the slave has become inaccessible,\n" +"InnoDB: and switch off synchronous replication until the communication.\n" +"InnoDB: to the slave works again.\n", + thd->variables.sync_replication_timeout); + fprintf(stderr, +"InnoDB: MySQL synchronous replication has sent binlog\n" +"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name, + (ulong)innobase_repl_pos); + fprintf(stderr, +"InnoDB: This transaction needs it to be sent up to\n" +"InnoDB: file %s, position %lu\n", trx->repl_wait_binlog_name, + (uint)trx->repl_wait_binlog_pos); + + innobase_repl_state = 0; + + pthread_mutex_unlock(&innobase_repl_cond_mutex); + + return(0); + } + + goto try_again; + } + return(0); } +/********************************************************************* +In synchronous replication, reports to InnoDB up to which binlog position +we have sent the binlog to the slave. Note that replication is synchronous +for one slave only. For other slaves, we do nothing in this function. This +function is used in a replication master. */ + +int +innobase_repl_report_sent_binlog( +/*=============================*/ + /* out: 0 */ + THD* thd, /* in: thread doing the binlog communication to + the slave */ + char* log_file_name, /* in: binlog file name */ + my_off_t end_offset) /* in: the offset in the binlog file up to + which we sent the contents to the slave */ +{ + int cmp; + ibool can_release_threads = 0; + + /* If synchronous replication is not switched on, or this thd is + sending binlog to a slave where we do not need synchronous replication, + then return immediately */ + + if (thd->server_id != thd->variables.sync_replication_slave_id) { + + /* Do nothing */ + + return(0); + } + + pthread_mutex_lock(&innobase_repl_cond_mutex); + + if (innobase_repl_state == 0) { + + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Switching MySQL synchronous replication on again at\n" +"InnoDB: binlog file %s, position %lu\n", log_file_name, (ulong)end_offset); + + innobase_repl_state = 1; + } + + /* The position should increase monotonically, since just one thread + is sending the binlog to the slave for which we want synchronous + replication. Let us check this, and print an error to the .err log + if that is not the case. */ + + if (innobase_repl_file_name_inited) { + cmp = strcmp(log_file_name, innobase_repl_file_name); + + if (cmp < 0 + || (cmp == 0 && end_offset < innobase_repl_pos)) { + + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Error: MySQL synchronous replication has sent binlog\n" +"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name, + (ulong)innobase_repl_pos); + fprintf(stderr, +"InnoDB: but now MySQL reports that it sent the binlog only up to\n" +"InnoDB: file %s, position %lu\n", log_file_name, (ulong)end_offset); + + } + } + + strcpy(innobase_repl_file_name, log_file_name); + innobase_repl_pos = end_offset; + innobase_repl_file_name_inited = 1; + + if (innobase_repl_n_wait_threads > 0) { + /* Let us check if some of the waiting threads doing a trx + commit can now proceed */ + + cmp = strcmp(innobase_repl_file_name, + innobase_repl_wait_file_name); + if (cmp > 0 + || (cmp == 0 && innobase_repl_pos + >= innobase_repl_wait_pos)) { + + /* Yes, at least one waiting thread can now proceed: + let us release all waiting threads with a broadcast */ + + can_release_threads = 1; + + innobase_repl_wait_file_name_inited = 0; + } + } + + pthread_mutex_unlock(&innobase_repl_cond_mutex); + + if (can_release_threads) { + + pthread_cond_broadcast(&innobase_repl_cond); + } +} + /********************************************************************* Rolls back a transaction or the latest SQL statement. */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 35f95ead757..6c412a889b2 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -321,3 +321,5 @@ int innobase_rollback_by_xid( int innobase_xa_end(THD *thd); +int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name, + my_off_t end_offset); diff --git a/sql/handler.cc b/sql/handler.cc index 14b8974ece9..6ab4f7824ed 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2411,3 +2411,60 @@ TYPELIB *ha_known_exts(void) } return &known_extensions; } + +/* + Reports to table handlers up to which position we have sent the binlog + to a slave in replication + + SYNOPSIS + ha_repl_report_sent_binlog() + + NOTES + Only works for InnoDB at the moment + + RETURN VALUE + Always 0 (= success) + + PARAMETERS + THD *thd in: thread doing the binlog communication to + the slave + char *log_file_name in: binlog file name + my_off_t end_offset in: the offset in the binlog file up to + which we sent the contents to the slave +*/ + +int ha_repl_report_sent_binlog(THD *thd, char *log_file_name, + my_off_t end_offset) +{ +#ifdef HAVE_INNOBASE_DB + return innobase_repl_report_sent_binlog(thd,log_file_name,end_offset); +#else + /* remove warnings about unused parameters */ + thd=thd; log_file_name=log_file_name; end_offset=end_offset; + return 0; +#endif +} + +/* + Reports to table handlers that we stop replication to a specific slave + + SYNOPSIS + ha_repl_report_replication_stop() + + NOTES + Does nothing at the moment + + RETURN VALUE + Always 0 (= success) + + PARAMETERS + THD *thd in: thread doing the binlog communication to + the slave +*/ + +int ha_repl_report_replication_stop(THD *thd) +{ + thd = thd; + + return 0; +} diff --git a/sql/handler.h b/sql/handler.h index 4c06fe8299d..5e25f038c36 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -843,7 +843,7 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache); int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); int ha_end_key_cache(KEY_CACHE *key_cache); -/* weird stuff */ +/* report to InnoDB that control passes to the client */ int ha_release_temporary_latches(THD *thd); /* transactions: interface to handlerton functions */ @@ -875,3 +875,7 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht); #define trans_need_2pc(thd, all) ((total_ha_2pc > 1) && \ !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc)) +/* semi-synchronous replication */ +int ha_repl_report_sent_binlog(THD *thd, char *log_file_name, + my_off_t end_offset); +int ha_repl_report_replication_stop(THD *thd); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9c592d068ee..214915a3cb0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5495,7 +5495,6 @@ The minimum value for this variable is 4096.", {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, -#ifdef DOES_NOTHING_YET {"sync-replication", OPT_SYNC_REPLICATION, "Enable synchronous replication.", (gptr*) &global_system_variables.sync_replication, @@ -5511,7 +5510,6 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.sync_replication_timeout, (gptr*) &global_system_variables.sync_replication_timeout, 0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0}, -#endif {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L, diff --git a/sql/set_var.cc b/sql/set_var.cc index 70d64b5dac6..09fc7b20dad 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -957,11 +957,9 @@ struct show_var_st init_vars[]= { {"sql_warnings", (char*) &sys_sql_warnings, SHOW_BOOL}, #ifdef HAVE_REPLICATION {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS}, -#ifdef DOES_NOTHING_YET {sys_sync_replication.name, (char*) &sys_sync_replication, SHOW_SYS}, {sys_sync_replication_slave_id.name, (char*) &sys_sync_replication_slave_id,SHOW_SYS}, {sys_sync_replication_timeout.name, (char*) &sys_sync_replication_timeout,SHOW_SYS}, -#endif #endif {sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS}, #ifdef HAVE_TZNAME diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 634b6ab0995..72470c487a3 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -385,6 +385,11 @@ impossible position"; goto err; } + printf("Binlog file name %s\n", log_file_name); + + if (thd->variables.sync_replication) + ha_repl_report_sent_binlog(thd, log_file_name, pos); + /* We need to start a packet with something other than 255 to distinguish it from error @@ -470,6 +475,10 @@ impossible position"; my_errno= ER_UNKNOWN_ERROR; goto err; } + + if (thd->variables.sync_replication) + ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log)); + /* No need to save this event. We are only doing simple reads (no real parsing of the events) so we don't need it. And so @@ -527,6 +536,13 @@ impossible position"; my_errno= ER_UNKNOWN_ERROR; goto err; } + + printf("Dump loop: %s: Current log position %lu\n", log_file_name, + (ulong)my_b_tell(&log)); + + if (thd->variables.sync_replication) + ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log)); + DBUG_PRINT("info", ("log event code %d", (*packet)[LOG_EVENT_OFFSET+1] )); if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) @@ -640,6 +656,12 @@ impossible position"; goto err; } + printf("Second loop: %s: Current log position %lu\n", log_file_name, + (ulong)my_b_tell(&log)); + + if (thd->variables.sync_replication) + ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log)); + if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) { if (send_file(thd)) @@ -704,12 +726,22 @@ impossible position"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; } + + if (thd->variables.sync_replication) + ha_repl_report_sent_binlog(thd, log_file_name, 0); + + printf("Binlog file name of a new binlog %s\n", log_file_name); + packet->length(0); packet->append('\0'); } } end: + printf("Ending replication\n"); + if (thd->variables.sync_replication) + ha_repl_report_replication_stop(thd); + end_io_cache(&log); (void)my_close(file, MYF(MY_WME)); @@ -721,6 +753,11 @@ end: DBUG_VOID_RETURN; err: + if (thd->variables.sync_replication) + ha_repl_report_replication_stop(thd); + + printf("Ending replication in error %s\n", errmsg); + thd->proc_info = "Waiting to finalize termination"; end_io_cache(&log); /* From 48ba5e495666fd5db051c1a1aa9d4d61a85f07c0 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 20 Apr 2005 20:10:28 +0200 Subject: [PATCH 07/47] Step 1 of the switch to support configuration with NPTL: Rename 'IS_LINUX' configuration variable to 'TARGET_LINUX'. --- acinclude.m4 | 2 +- configure.in | 18 +++++++++--------- myisam/Makefile.am | 2 +- scripts/Makefile.am | 2 +- scripts/mysqld_safe.sh | 2 +- support-files/Makefile.am | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 74426bc2061..a81a4fa5c3f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -976,7 +976,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then echo "Could not find an installation of OpenSSL" if test -n "$OPENSSL_LIB" ; then - if test "$IS_LINUX" = "true"; then + if test "$TARGET_LINUX" = "true"; then echo "Looks like you've forgotten to install OpenSSL development RPM" fi fi diff --git a/configure.in b/configure.in index d191463d0f9..6650c0fc64a 100644 --- a/configure.in +++ b/configure.in @@ -410,15 +410,15 @@ AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") if expr "$target_os" : "[[Ll]]inux.*" > /dev/null then MYSQLD_DEFAULT_SWITCHES="--skip-locking" - IS_LINUX="true" + TARGET_LINUX="true" AC_MSG_RESULT("yes"); else MYSQLD_DEFAULT_SWITCHES="" - IS_LINUX="false" + TARGET_LINUX="false" AC_MSG_RESULT("no"); fi AC_SUBST(MYSQLD_DEFAULT_SWITCHES) -AC_SUBST(IS_LINUX) +AC_SUBST(TARGET_LINUX) dnl Find paths to some shell programs AC_PATH_PROG(LN, ln, ln) @@ -607,7 +607,7 @@ AC_SUBST(NOINST_LDFLAGS) # (this is true on the MySQL build machines to avoid NSS problems) # -if test "$IS_LINUX" = "true" -a "$static_nss" = "" +if test "$TARGET_LINUX" = "true" -a "$static_nss" = "" then tmp=`nm /usr/lib/libc.a | grep _nss_files_getaliasent_r` if test -n "$tmp" @@ -841,7 +841,7 @@ struct request_info *req; ]) AC_SUBST(WRAPLIBS) -if test "$IS_LINUX" = "true"; then +if test "$TARGET_LINUX" = "true"; then AC_MSG_CHECKING([for atomic operations]) atom_ops= @@ -885,7 +885,7 @@ int main() [ USE_PSTACK=no ]) pstack_libs= pstack_dirs= - if test "$USE_PSTACK" = yes -a "$IS_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no" + if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no" then have_libiberty= have_libbfd= my_save_LIBS="$LIBS" @@ -1286,7 +1286,7 @@ then else AC_MSG_RESULT("Not found") # If this is a linux machine we should barf - if test "$IS_LINUX" = "true" + if test "$TARGET_LINUX" = "true" then AC_MSG_ERROR([This is a linux system and Linuxthreads was not found. On linux Linuxthreads should be used. Please install Linuxthreads @@ -1738,7 +1738,7 @@ fi AC_SUBST(COMPILATION_COMMENT) AC_MSG_CHECKING("need of special linking flags") -if test "$IS_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes" +if test "$TARGET_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes" then LDFLAGS="$LDFLAGS -rdynamic" AC_MSG_RESULT("-rdynamic") @@ -1955,7 +1955,7 @@ CFLAGS="$ORG_CFLAGS" # Sanity check: We chould not have any fseeko symbol unless # large_file_support=yes AC_CHECK_FUNC(fseeko, -[if test "$large_file_support" = no -a "$IS_LINUX" = "true"; +[if test "$large_file_support" = no -a "$TARGET_LINUX" = "true"; then AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!"); fi] diff --git a/myisam/Makefile.am b/myisam/Makefile.am index 378e8107814..0b8a25e3404 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -88,7 +88,7 @@ SUFFIXES = .sh -e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \ diff --git a/scripts/Makefile.am b/scripts/Makefile.am index b170fa483b2..e2ef1bba97c 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -135,7 +135,7 @@ SUFFIXES = .sh -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''STATIC_NSS_FLAGS''@!@STATIC_NSS_FLAGS@!' \ diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 308db270828..8a232f4f7f9 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -324,7 +324,7 @@ do break fi - if @IS_LINUX@ && test $KILL_MYSQLD -eq 1 + if @TARGET_LINUX@ && test $KILL_MYSQLD -eq 1 then # Test if one process was hanging. # This is only a fix for Linux (running as base 3 mysqld processes) diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 0a6077f0efc..5f5a10fc1fc 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -90,7 +90,7 @@ SUFFIXES = .sh -e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \ From eaa79cb45234f4a675919cb4565adac45601e971 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 20 Apr 2005 20:38:57 +0200 Subject: [PATCH 08/47] Step 2 of the switch to support configuration with NPTL: Define a new CPP symbol that the target OS is Linux, and use it where only the OS matters and not the threads Library. Until now, 'HAVE_LINUXTHREADS' was used to indicate "Target is Linux" in many places. When we support configuration with NPTL but no Linuxthreads, this misuse must cease. --- configure.in | 1 + include/my_global.h | 8 ++++---- mysys/thr_mutex.c | 2 +- sql/stacktrace.c | 4 ++-- sql/stacktrace.h | 4 ++-- tools/mysqlmanager.c | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/configure.in b/configure.in index 6650c0fc64a..f7a266eebec 100644 --- a/configure.in +++ b/configure.in @@ -412,6 +412,7 @@ then MYSQLD_DEFAULT_SWITCHES="--skip-locking" TARGET_LINUX="true" AC_MSG_RESULT("yes"); + AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" TARGET_LINUX="false" diff --git a/include/my_global.h b/include/my_global.h index 23cf0d54824..a027bf9d2bb 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -97,7 +97,7 @@ /* Fix problem with S_ISLNK() on Linux */ -#if defined(HAVE_LINUXTHREADS) +#if defined(TARGET_OS_LINUX) #undef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -214,13 +214,13 @@ C_MODE_START int __cxa_pure_virtual() {\ #endif /* In Linux-alpha we have atomic.h if we are using gcc */ -#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD) +#if defined(TARGET_OS_LINUX) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD) #define HAVE_ATOMIC_ADD #define HAVE_ATOMIC_SUB #endif /* In Linux-ia64 including atomic.h will give us an error */ -#if (defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD) +#if (defined(TARGET_OS_LINUX) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD) #undef HAVE_ATOMIC_ADD #undef HAVE_ATOMIC_SUB #endif @@ -755,7 +755,7 @@ typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */ error "Neither int or long is of 4 bytes width" #endif -#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC) +#if !defined(HAVE_ULONG) && !defined(TARGET_OS_LINUX) && !defined(__USE_MISC) typedef unsigned long ulong; /* Short for unsigned long */ #endif #ifndef longlong_defined diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index bbcfaa8bba6..2facb4e18cf 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -17,7 +17,7 @@ /* This makes a wrapper for mutex handling to make it easier to debug mutex */ #include -#if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98) +#if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98) #define __USE_UNIX98 /* To get rw locks under Linux */ #endif #if defined(THREAD) && defined(SAFE_MUTEX) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 322d647e741..838f547dc02 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -43,7 +43,7 @@ void safe_print_str(const char* name, const char* val, int max_len) fputc('\n', stderr); } -#ifdef HAVE_LINUXTHREADS +#ifdef TARGET_OS_LINUX #define SIGRETURN_FRAME_COUNT 2 #if defined(__alpha__) && defined(__GNUC__) @@ -201,7 +201,7 @@ end: stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } -#endif /* HAVE_LINUXTHREADS */ +#endif /* TARGET_OS_LINUX */ #endif /* HAVE_STACKTRACE */ /* Produce a core for the thread */ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index 980e1ea07eb..d5d1e05ef0e 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -18,7 +18,7 @@ extern "C" { #endif -#ifdef HAVE_LINUXTHREADS +#ifdef TARGET_OS_LINUX #if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE @@ -30,7 +30,7 @@ extern char* heap_start; void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ -#endif /* HAVE_LINUXTHREADS */ +#endif /* TARGET_OS_LINUX */ /* Define empty prototypes for functions that are not implemented */ #ifndef HAVE_STACKTRACE diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index bb0a76d6c49..27caa1e0255 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -101,7 +101,7 @@ static CHARSET_INFO *cs= &my_charset_latin1; set by the user */ -#if defined(__i386__) && defined(HAVE_LINUXTHREADS) +#if defined(__i386__) && defined(TARGET_OS_LINUX) #define DO_STACKTRACE 1 #endif From 50ada0a01c9cd9a0d50f82db44de19d07fcee986 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Thu, 21 Apr 2005 21:06:08 +0500 Subject: [PATCH 09/47] A fix (Bug #9489: Problem with BIT_OR and MySQL 5.0.3) --- heap/hp_hash.c | 11 +++++++++++ mysql-test/r/type_varchar.result | 11 ++++++++++- mysql-test/t/type_varchar.test | 14 +++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 3121ef71fb0..52a250bd7af 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -255,6 +255,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) if (*pos) /* Found null */ { nr^= (nr << 1) | 1; + /* Add key pack length (2) to key for VARCHAR segments */ + if (seg->type == HA_KEYTYPE_VARTEXT1) + key+= 2; continue; } pos++; @@ -390,6 +393,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) if (*pos) { nr^= (nr << 1) | 1; + /* Add key pack length (2) to key for VARCHAR segments */ + if (seg->type == HA_KEYTYPE_VARTEXT1) + key+= 2; continue; } pos++; @@ -584,7 +590,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key) if (found_null != (int) *key++) return 1; if (found_null) + { + /* Add key pack length (2) to key for VARCHAR segments */ + if (seg->type == HA_KEYTYPE_VARTEXT1) + key+= 2; continue; + } } if (seg->type == HA_KEYTYPE_TEXT) { diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index d2fe843a68b..3bd7fe6b175 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1, t2; create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text); truncate table vchar; show create table t1; @@ -383,3 +383,12 @@ select * from t1; pkcol othercol test somethingelse drop table t1; +create table t1 (a int, b varchar(12)); +insert into t1 values (1, 'A'), (22, NULL); +create table t2 (a int); +insert into t2 values (22), (22); +select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a +group by t1.b, t1.a; +a b min(t1.b) +22 NULL NULL +drop table t1, t2; diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 9867cf4c057..2bffca6b889 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -1,5 +1,5 @@ --disable_warnings -drop table if exists t1; +drop table if exists t1, t2; --enable_warnings create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text); @@ -106,3 +106,15 @@ insert into t1 values ('test', 'something'); update t1 set othercol='somethingelse' where pkcol='test'; select * from t1; drop table t1; + +# +# Bug #9489: problems with key handling +# + +create table t1 (a int, b varchar(12)); +insert into t1 values (1, 'A'), (22, NULL); +create table t2 (a int); +insert into t2 values (22), (22); +select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a + group by t1.b, t1.a; +drop table t1, t2; From e6142c477c036a0d16e0fe812d6d238419c2b475 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Fri, 22 Apr 2005 09:07:25 +0200 Subject: [PATCH 10/47] bug#9924 - ndb backup abort handling Redo abort handling according to descr. in Backup.txt bug#9960 - ndb backup increase wait completed timeout to 48 hours --- ndb/include/kernel/signaldata/BackupImpl.hpp | 12 +- .../kernel/signaldata/BackupSignalData.hpp | 3 + .../common/debugger/signaldata/BackupImpl.cpp | 6 +- ndb/src/kernel/blocks/backup/Backup.cpp | 1508 +++++++---------- ndb/src/kernel/blocks/backup/Backup.hpp | 36 +- ndb/src/kernel/blocks/backup/Backup.txt | 25 + ndb/src/kernel/blocks/backup/BackupInit.cpp | 2 +- ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp | 1 + ndb/src/mgmapi/mgmapi.cpp | 4 +- ndb/src/mgmsrv/MgmtSrvr.cpp | 29 +- ndb/src/mgmsrv/MgmtSrvr.hpp | 4 +- .../mgmsrv/MgmtSrvrGeneralSignalHandling.cpp | 6 +- ndb/src/ndbapi/ndberror.c | 5 +- ndb/test/ndbapi/testBackup.cpp | 14 +- ndb/test/run-test/daily-basic-tests.txt | 24 + ndb/test/src/NdbBackup.cpp | 46 +- 16 files changed, 758 insertions(+), 967 deletions(-) diff --git a/ndb/include/kernel/signaldata/BackupImpl.hpp b/ndb/include/kernel/signaldata/BackupImpl.hpp index 2ac91570aad..2032e2347b5 100644 --- a/ndb/include/kernel/signaldata/BackupImpl.hpp +++ b/ndb/include/kernel/signaldata/BackupImpl.hpp @@ -75,7 +75,7 @@ class DefineBackupRef { friend bool printDEFINE_BACKUP_REF(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( SignalLength = 4 ); enum ErrorCode { Undefined = 1340, @@ -92,6 +92,7 @@ private: Uint32 backupId; Uint32 backupPtr; Uint32 errorCode; + Uint32 nodeId; }; class DefineBackupConf { @@ -158,7 +159,7 @@ class StartBackupRef { friend bool printSTART_BACKUP_REF(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( SignalLength = 5 ); enum ErrorCode { FailedToAllocateTriggerRecord = 1 @@ -168,6 +169,7 @@ private: Uint32 backupPtr; Uint32 signalNo; Uint32 errorCode; + Uint32 nodeId; }; class StartBackupConf { @@ -232,9 +234,8 @@ public: private: Uint32 backupId; Uint32 backupPtr; - Uint32 tableId; - Uint32 fragmentNo; Uint32 errorCode; + Uint32 nodeId; }; class BackupFragmentConf { @@ -296,12 +297,13 @@ class StopBackupRef { friend bool printSTOP_BACKUP_REF(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( SignalLength = 4 ); private: Uint32 backupId; Uint32 backupPtr; Uint32 errorCode; + Uint32 nodeId; }; class StopBackupConf { diff --git a/ndb/include/kernel/signaldata/BackupSignalData.hpp b/ndb/include/kernel/signaldata/BackupSignalData.hpp index fb018026a49..b38dd8d14b2 100644 --- a/ndb/include/kernel/signaldata/BackupSignalData.hpp +++ b/ndb/include/kernel/signaldata/BackupSignalData.hpp @@ -240,6 +240,9 @@ public: FileOrScanError = 1325, // slave -> coordinator BackupFailureDueToNodeFail = 1326, // slave -> slave OkToClean = 1327 // master -> slave + + ,AbortScan = 1328 + ,IncompatibleVersions = 1329 }; private: Uint32 requestType; diff --git a/ndb/src/common/debugger/signaldata/BackupImpl.cpp b/ndb/src/common/debugger/signaldata/BackupImpl.cpp index bdc34d614cf..e9b0188d93b 100644 --- a/ndb/src/common/debugger/signaldata/BackupImpl.cpp +++ b/ndb/src/common/debugger/signaldata/BackupImpl.cpp @@ -90,10 +90,8 @@ printBACKUP_FRAGMENT_REQ(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){ bool printBACKUP_FRAGMENT_REF(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){ BackupFragmentRef* sig = (BackupFragmentRef*)data; - fprintf(out, " backupPtr: %d backupId: %d\n", - sig->backupPtr, sig->backupId); - fprintf(out, " tableId: %d fragmentNo: %d errorCode: %d\n", - sig->tableId, sig->fragmentNo, sig->errorCode); + fprintf(out, " backupPtr: %d backupId: %d nodeId: %d errorCode: %d\n", + sig->backupPtr, sig->backupId, sig->nodeId, sig->errorCode); return true; } diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 2e62979ce8e..713991a4f58 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -67,31 +67,6 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000; //#define DEBUG_ABORT -//--------------------------------------------------------- -// Ignore this since a completed abort could have preceded -// this message. -//--------------------------------------------------------- -#define slaveAbortCheck() \ -if ((ptr.p->backupId != backupId) || \ - (ptr.p->slaveState.getState() == ABORTING)) { \ - jam(); \ - return; \ -} - -#define masterAbortCheck() \ -if ((ptr.p->backupId != backupId) || \ - (ptr.p->masterData.state.getState() == ABORTING)) { \ - jam(); \ - return; \ -} - -#define defineSlaveAbortCheck() \ - if (ptr.p->slaveState.getState() == ABORTING) { \ - jam(); \ - closeFiles(signal, ptr); \ - return; \ - } - static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE; void @@ -221,12 +196,7 @@ Backup::execCONTINUEB(Signal* signal) jam(); BackupRecordPtr ptr; c_backupPool.getPtr(ptr, Tdata1); - - if (ptr.p->slaveState.getState() == ABORTING) { - jam(); - closeFiles(signal, ptr); - return; - }//if + BackupFilePtr filePtr; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); FsBuffer & buf = filePtr.p->operation.dataBuffer; @@ -324,13 +294,7 @@ Backup::execDUMP_STATE_ORD(Signal* signal) for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){ infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x", ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef); - if(ptr.p->masterRef == reference()){ - infoEvent(" MasterState: %d State: %d", - ptr.p->masterData.state.getState(), - ptr.p->slaveState.getState()); - } else { - infoEvent(" State: %d", ptr.p->slaveState.getState()); - } + infoEvent(" State: %d", ptr.p->slaveState.getState()); BackupFilePtr filePtr; for(ptr.p->files.first(filePtr); filePtr.i != RNIL; ptr.p->files.next(filePtr)){ @@ -338,7 +302,7 @@ Backup::execDUMP_STATE_ORD(Signal* signal) infoEvent(" file %d: type: %d open: %d running: %d done: %d scan: %d", filePtr.i, filePtr.p->fileType, filePtr.p->fileOpened, filePtr.p->fileRunning, - filePtr.p->fileDone, filePtr.p->scanRunning); + filePtr.p->fileClosing, filePtr.p->scanRunning); } } } @@ -356,6 +320,17 @@ Backup::execDUMP_STATE_ORD(Signal* signal) infoEvent("PagePool: %d", c_pagePool.getSize()); + + if(signal->getLength() == 2 && signal->theData[1] == 2424) + { + ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree()); + ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree()); + ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree()); + ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree()); + ndbrequire(c_pagePool.getSize() == c_pagePool.getNoOfFree()); + ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree()); + ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree()); + } } } @@ -511,27 +486,6 @@ const char* triggerNameFormat[] = { "NDB$BACKUP_%d_%d_DELETE" }; -const Backup::State -Backup::validMasterTransitions[] = { - INITIAL, DEFINING, - DEFINING, DEFINED, - DEFINED, STARTED, - STARTED, SCANNING, - SCANNING, STOPPING, - STOPPING, INITIAL, - - DEFINING, ABORTING, - DEFINED, ABORTING, - STARTED, ABORTING, - SCANNING, ABORTING, - STOPPING, ABORTING, - ABORTING, ABORTING, - - DEFINING, INITIAL, - ABORTING, INITIAL, - INITIAL, INITIAL -}; - const Backup::State Backup::validSlaveTransitions[] = { INITIAL, DEFINING, @@ -561,10 +515,6 @@ const Uint32 Backup::validSlaveTransitionsCount = sizeof(Backup::validSlaveTransitions) / sizeof(Backup::State); -const Uint32 -Backup::validMasterTransitionsCount = -sizeof(Backup::validMasterTransitions) / sizeof(Backup::State); - void Backup::CompoundState::setState(State newState){ bool found = false; @@ -578,7 +528,8 @@ Backup::CompoundState::setState(State newState){ break; } } - ndbrequire(found); + + //ndbrequire(found); if (newState == INITIAL) abortState = INITIAL; @@ -647,8 +598,7 @@ Backup::execNODE_FAILREP(Signal* signal) Uint32 theFailedNodes[NodeBitmask::Size]; for (Uint32 i = 0; i < NodeBitmask::Size; i++) theFailedNodes[i] = rep->theNodes[i]; - -// NodeId old_master_node_id = getMasterNodeId(); + c_masterNodeId = new_master_node_id; NodePtr nodePtr; @@ -686,15 +636,24 @@ Backup::execNODE_FAILREP(Signal* signal) } bool -Backup::verifyNodesAlive(const NdbNodeBitmask& aNodeBitMask) +Backup::verifyNodesAlive(BackupRecordPtr ptr, + const NdbNodeBitmask& aNodeBitMask) { + Uint32 version = getNodeInfo(getOwnNodeId()).m_version; for (Uint32 i = 0; i < MAX_NDB_NODES; i++) { jam(); if(aNodeBitMask.get(i)) { if(!c_aliveNodes.get(i)){ jam(); + ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail); return false; }//if + if(getNodeInfo(i).m_version != version) + { + jam(); + ptr.p->setErrorCode(AbortBackupOrd::IncompatibleVersions); + return false; + } }//if }//for return true; @@ -709,6 +668,10 @@ Backup::checkNodeFail(Signal* signal, ndbrequire( ptr.p->nodes.get(newCoord)); /* just to make sure newCoord * is part of the backup */ + + NdbNodeBitmask mask; + mask.assign(2, theFailedNodes); + /* Update ptr.p->nodes to be up to date with current alive nodes */ NodePtr nodePtr; @@ -730,26 +693,42 @@ Backup::checkNodeFail(Signal* signal, return; // failed node is not part of backup process, safe to continue } - bool doMasterTakeover = false; - if(NodeBitmask::get(theFailedNodes, refToNode(ptr.p->masterRef))){ - jam(); - doMasterTakeover = true; - }; - - if (newCoord == getOwnNodeId()){ - jam(); - if (doMasterTakeover) { - /** - * I'm new master - */ - CRASH_INSERTION((10002)); -#ifdef DEBUG_ABORT - ndbout_c("**** Master Takeover: Node failed: Master id = %u", - refToNode(ptr.p->masterRef)); -#endif - masterTakeOver(signal, ptr); + if(mask.get(refToNode(ptr.p->masterRef))) + { + /** + * Master died...abort + */ + ptr.p->masterRef = reference(); + ptr.p->nodes.clear(); + ptr.p->nodes.set(getOwnNodeId()); + ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail); + switch(ptr.p->m_gsn){ + case GSN_DEFINE_BACKUP_REQ: + case GSN_START_BACKUP_REQ: + case GSN_BACKUP_FRAGMENT_REQ: + case GSN_STOP_BACKUP_REQ: + // I'm currently processing...reply to self and abort... + ptr.p->masterData.gsn = ptr.p->m_gsn; + ptr.p->masterData.sendCounter = ptr.p->nodes; return; - }//if + case GSN_DEFINE_BACKUP_REF: + case GSN_DEFINE_BACKUP_CONF: + case GSN_START_BACKUP_REF: + case GSN_START_BACKUP_CONF: + case GSN_BACKUP_FRAGMENT_REF: + case GSN_BACKUP_FRAGMENT_CONF: + case GSN_STOP_BACKUP_REF: + case GSN_STOP_BACKUP_CONF: + ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ; + masterAbort(signal, ptr); + return; + case GSN_ABORT_BACKUP_ORD: + // Already aborting + return; + } + } + else if (newCoord == getOwnNodeId()) + { /** * I'm master for this backup */ @@ -759,61 +738,81 @@ Backup::checkNodeFail(Signal* signal, ndbout_c("**** Master: Node failed: Master id = %u", refToNode(ptr.p->masterRef)); #endif - masterAbort(signal, ptr, false); + + Uint32 gsn, len, pos; + ptr.p->nodes.bitANDC(mask); + switch(ptr.p->masterData.gsn){ + case GSN_DEFINE_BACKUP_REQ: + { + DefineBackupRef * ref = (DefineBackupRef*)signal->getDataPtr(); + ref->backupPtr = ptr.i; + ref->backupId = ptr.p->backupId; + ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; + gsn= GSN_DEFINE_BACKUP_REF; + len= DefineBackupRef::SignalLength; + pos= &ref->nodeId - signal->getDataPtr(); + break; + } + case GSN_START_BACKUP_REQ: + { + StartBackupRef * ref = (StartBackupRef*)signal->getDataPtr(); + ref->backupPtr = ptr.i; + ref->backupId = ptr.p->backupId; + ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; + ref->signalNo = ptr.p->masterData.startBackup.signalNo; + gsn= GSN_START_BACKUP_REF; + len= StartBackupRef::SignalLength; + pos= &ref->nodeId - signal->getDataPtr(); + break; + } + case GSN_BACKUP_FRAGMENT_REQ: + { + BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr(); + ref->backupPtr = ptr.i; + ref->backupId = ptr.p->backupId; + ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; + gsn= GSN_BACKUP_FRAGMENT_REF; + len= BackupFragmentRef::SignalLength; + pos= &ref->nodeId - signal->getDataPtr(); + break; + } + case GSN_STOP_BACKUP_REQ: + { + StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr(); + ref->backupPtr = ptr.i; + ref->backupId = ptr.p->backupId; + ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; + gsn= GSN_STOP_BACKUP_REF; + len= StopBackupRef::SignalLength; + pos= &ref->nodeId - signal->getDataPtr(); + break; + } + case GSN_CREATE_TRIG_REQ: + case GSN_ALTER_TRIG_REQ: + case GSN_WAIT_GCP_REQ: + case GSN_UTIL_SEQUENCE_REQ: + case GSN_UTIL_LOCK_REQ: + case GSN_DROP_TRIG_REQ: + return; + } + + for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; ) + { + signal->theData[pos] = i; + sendSignal(reference(), gsn, signal, len, JBB); +#ifdef DEBUG_ABORT + ndbout_c("sending %d to self from %d", gsn, i); +#endif + } return; }//if - - /** - * If there's a new master, (it's not me) - * but remember who it is - */ - ptr.p->masterRef = calcBackupBlockRef(newCoord); -#ifdef DEBUG_ABORT - ndbout_c("**** Slave: Node failed: Master id = %u", - refToNode(ptr.p->masterRef)); -#endif + /** * I abort myself as slave if not master */ CRASH_INSERTION((10021)); - // slaveAbort(signal, ptr); } -void -Backup::masterTakeOver(Signal* signal, BackupRecordPtr ptr) -{ - ptr.p->masterRef = reference(); - ptr.p->masterData.gsn = MAX_GSN + 1; - - switch(ptr.p->slaveState.getState()){ - case INITIAL: - jam(); - ptr.p->masterData.state.forceState(INITIAL); - break; - case ABORTING: - jam(); - case DEFINING: - jam(); - case DEFINED: - jam(); - case STARTED: - jam(); - case SCANNING: - jam(); - ptr.p->masterData.state.forceState(STARTED); - break; - case STOPPING: - jam(); - case CLEANING: - jam(); - ptr.p->masterData.state.forceState(STOPPING); - break; - default: - ndbrequire(false); - } - masterAbort(signal, ptr, false); -} - void Backup::execINCL_NODEREQ(Signal* signal) { @@ -895,8 +894,8 @@ Backup::execBACKUP_REQ(Signal* signal) ndbrequire(ptr.p->pages.empty()); ndbrequire(ptr.p->tables.isEmpty()); - ptr.p->masterData.state.forceState(INITIAL); - ptr.p->masterData.state.setState(DEFINING); + ptr.p->m_gsn = 0; + ptr.p->errorCode = 0; ptr.p->clientRef = senderRef; ptr.p->clientData = senderData; ptr.p->masterRef = reference(); @@ -905,6 +904,7 @@ Backup::execBACKUP_REQ(Signal* signal) ptr.p->backupKey[0] = 0; ptr.p->backupKey[1] = 0; ptr.p->backupDataLen = 0; + ptr.p->masterData.errorCode = 0; ptr.p->masterData.dropTrig.tableId = RNIL; ptr.p->masterData.alterTrig.tableId = RNIL; @@ -928,7 +928,6 @@ Backup::execUTIL_SEQUENCE_REF(Signal* signal) ndbrequire(ptr.i == RNIL); c_backupPool.getPtr(ptr); ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ); - ptr.p->masterData.gsn = 0; sendBackupRef(signal, ptr, BackupRef::SequenceFailure); }//execUTIL_SEQUENCE_REF() @@ -938,8 +937,7 @@ Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode) { jam(); sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode); - // ptr.p->masterData.state.setState(INITIAL); - cleanupSlaveResources(ptr); + cleanup(signal, ptr); } void @@ -968,7 +966,8 @@ Backup::execUTIL_SEQUENCE_CONF(Signal* signal) UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr(); - if(conf->requestType == UtilSequenceReq::Create) { + if(conf->requestType == UtilSequenceReq::Create) + { jam(); sendSTTORRY(signal); // At startup in NDB return; @@ -979,18 +978,20 @@ Backup::execUTIL_SEQUENCE_CONF(Signal* signal) c_backupPool.getPtr(ptr); ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ); - ptr.p->masterData.gsn = 0; - if (ptr.p->masterData.state.getState() == ABORTING) { + + if (ptr.p->checkError()) + { jam(); sendBackupRef(signal, ptr, ptr.p->errorCode); return; }//if - if (ERROR_INSERTED(10023)) { - ptr.p->masterData.state.setState(ABORTING); + + if (ERROR_INSERTED(10023)) + { sendBackupRef(signal, ptr, 323); return; }//if - ndbrequire(ptr.p->masterData.state.getState() == DEFINING); + { Uint64 backupId; @@ -1018,7 +1019,6 @@ Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){ c_backupPool.getPtr(ptr); ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ); - ptr.p->masterData.gsn = 0; ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ; Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex); @@ -1040,14 +1040,13 @@ Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal) c_backupPool.getPtr(ptr); ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ); - ptr.p->masterData.gsn = 0; if (ERROR_INSERTED(10031)) { - ptr.p->masterData.state.setState(ABORTING); ptr.p->setErrorCode(331); }//if - if (ptr.p->masterData.state.getState() == ABORTING) { + if (ptr.p->checkError()) + { jam(); /** @@ -1062,13 +1061,11 @@ Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal) Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex); jam(); mutex2.unlock(); // ignore response - + sendBackupRef(signal, ptr, ptr.p->errorCode); return; }//if - ndbrequire(ptr.p->masterData.state.getState() == DEFINING); - sendDefineBackupReq(signal, ptr); } @@ -1078,33 +1075,6 @@ Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal) * *****************************************************************************/ -void -Backup::sendSignalAllWait(BackupRecordPtr ptr, Uint32 gsn, Signal *signal, - Uint32 signalLength, bool executeDirect) -{ - jam(); - ptr.p->masterData.gsn = gsn; - ptr.p->masterData.sendCounter.clearWaitingFor(); - NodePtr node; - for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)){ - jam(); - const Uint32 nodeId = node.p->nodeId; - if(node.p->alive && ptr.p->nodes.get(nodeId)){ - jam(); - - ptr.p->masterData.sendCounter.setWaitingFor(nodeId); - - const BlockReference ref = numberToRef(BACKUP, nodeId); - if (!executeDirect || ref != reference()) { - sendSignal(ref, gsn, signal, signalLength, JBB); - }//if - }//if - }//for - if (executeDirect) { - EXECUTE_DIRECT(BACKUP, gsn, signal, signalLength); - } -} - bool Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId) { @@ -1114,10 +1084,6 @@ Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId) ndbrequire(ptr.p->masterData.sendCounter.isWaitingFor(nodeId)); ptr.p->masterData.sendCounter.clearWaitingFor(nodeId); - - if (ptr.p->masterData.sendCounter.done()) - ptr.p->masterData.gsn = 0; - return ptr.p->masterData.sendCounter.done(); } @@ -1138,11 +1104,12 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr) req->nodes = ptr.p->nodes; req->backupDataLen = ptr.p->backupDataLen; - ptr.p->masterData.errorCode = 0; - ptr.p->okToCleanMaster = false; // master must wait with cleaning to last - sendSignalAllWait(ptr, GSN_DEFINE_BACKUP_REQ, signal, - DefineBackupReq::SignalLength, - true /* do execute direct on oneself */); + ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ; + ptr.p->masterData.sendCounter = ptr.p->nodes; + NodeReceiverGroup rg(BACKUP, ptr.p->nodes); + sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal, + DefineBackupReq::SignalLength, JBB); + /** * Now send backup data */ @@ -1167,17 +1134,15 @@ Backup::execDEFINE_BACKUP_REF(Signal* signal) jamEntry(); DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtr(); - + const Uint32 ptrI = ref->backupPtr; - const Uint32 backupId = ref->backupId; - const Uint32 nodeId = refToNode(signal->senderBlockRef()); - + //const Uint32 backupId = ref->backupId; + const Uint32 nodeId = ref->nodeId; + BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - - masterAbortCheck(); // macro will do return if ABORTING - ptr.p->masterData.errorCode = ref->errorCode; + ptr.p->setErrorCode(ref->errorCode); defineBackupReply(signal, ptr, nodeId); } @@ -1188,17 +1153,16 @@ Backup::execDEFINE_BACKUP_CONF(Signal* signal) DefineBackupConf* conf = (DefineBackupConf*)signal->getDataPtr(); const Uint32 ptrI = conf->backupPtr; - const Uint32 backupId = conf->backupId; + //const Uint32 backupId = conf->backupId; const Uint32 nodeId = refToNode(signal->senderBlockRef()); BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING - - if (ERROR_INSERTED(10024)) { - ptr.p->masterData.errorCode = 324; - }//if + if (ERROR_INSERTED(10024)) + { + ptr.p->setErrorCode(324); + } defineBackupReply(signal, ptr, nodeId); } @@ -1210,6 +1174,7 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) jam(); return; } + /** * Unlock mutexes */ @@ -1223,16 +1188,10 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) jam(); mutex2.unlock(); // ignore response - if(ptr.p->errorCode) { + if(ptr.p->checkError()) + { jam(); - ptr.p->masterData.errorCode = ptr.p->errorCode; - } - - if(ptr.p->masterData.errorCode){ - jam(); - ptr.p->setErrorCode(ptr.p->masterData.errorCode); - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::OkToClean); - masterSendAbortBackup(signal, ptr); + masterAbort(signal, ptr); return; } @@ -1252,7 +1211,6 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB); - ptr.p->masterData.state.setState(DEFINED); /** * Prepare Trig */ @@ -1286,7 +1244,6 @@ Backup::sendCreateTrig(Signal* signal, { CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend(); - ptr.p->errorCode = 0; ptr.p->masterData.gsn = GSN_CREATE_TRIG_REQ; ptr.p->masterData.sendCounter = 3; ptr.p->masterData.createTrig.tableId = tabPtr.p->tableId; @@ -1395,17 +1352,14 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr) return; }//if - ptr.p->masterData.gsn = 0; + if (ERROR_INSERTED(10025)) + { + ptr.p->errorCode = 325; + } if(ptr.p->checkError()) { jam(); - masterAbort(signal, ptr, true); - return; - }//if - - if (ERROR_INSERTED(10025)) { - ptr.p->errorCode = 325; - masterAbort(signal, ptr, true); + masterAbort(signal, ptr); return; }//if @@ -1425,10 +1379,7 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr) /** * Finished with all tables, send StartBackupReq */ - ptr.p->masterData.state.setState(STARTED); - ptr.p->tables.first(tabPtr); - ptr.p->errorCode = 0; ptr.p->masterData.startBackup.signalNo = 0; ptr.p->masterData.startBackup.noOfSignals = (ptr.p->tables.noOfElements() + StartBackupReq::MaxTableTriggers - 1) / @@ -1467,9 +1418,12 @@ Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr) }//for req->noOfTableTriggers = i; - sendSignalAllWait(ptr, GSN_START_BACKUP_REQ, signal, - StartBackupReq::HeaderLength + - (i * StartBackupReq::TableTriggerLength)); + ptr.p->masterData.gsn = GSN_START_BACKUP_REQ; + ptr.p->masterData.sendCounter = ptr.p->nodes; + NodeReceiverGroup rg(BACKUP, ptr.p->nodes); + sendSignal(rg, GSN_START_BACKUP_REQ, signal, + StartBackupReq::HeaderLength + + (i * StartBackupReq::TableTriggerLength), JBB); } void @@ -1479,15 +1433,13 @@ Backup::execSTART_BACKUP_REF(Signal* signal) StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr(); const Uint32 ptrI = ref->backupPtr; - const Uint32 backupId = ref->backupId; + //const Uint32 backupId = ref->backupId; const Uint32 signalNo = ref->signalNo; - const Uint32 nodeId = refToNode(signal->senderBlockRef()); + const Uint32 nodeId = ref->nodeId; BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING - ptr.p->setErrorCode(ref->errorCode); startBackupReply(signal, ptr, nodeId, signalNo); } @@ -1499,15 +1451,13 @@ Backup::execSTART_BACKUP_CONF(Signal* signal) StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr(); const Uint32 ptrI = conf->backupPtr; - const Uint32 backupId = conf->backupId; + //const Uint32 backupId = conf->backupId; const Uint32 signalNo = conf->signalNo; const Uint32 nodeId = refToNode(signal->senderBlockRef()); BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING - startBackupReply(signal, ptr, nodeId, signalNo); } @@ -1524,17 +1474,16 @@ Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, return; } + if (ERROR_INSERTED(10026)) + { + ptr.p->errorCode = 326; + } + if(ptr.p->checkError()){ jam(); - masterAbort(signal, ptr, true); + masterAbort(signal, ptr); return; } - - if (ERROR_INSERTED(10026)) { - ptr.p->errorCode = 326; - masterAbort(signal, ptr, true); - return; - }//if TablePtr tabPtr; c_tablePool.getPtr(tabPtr, ptr.p->masterData.startBackup.tablePtr); @@ -1566,7 +1515,6 @@ Backup::sendAlterTrig(Signal* signal, BackupRecordPtr ptr) { AlterTrigReq * req =(AlterTrigReq *)signal->getDataPtrSend(); - ptr.p->errorCode = 0; ptr.p->masterData.gsn = GSN_ALTER_TRIG_REQ; ptr.p->masterData.sendCounter = 0; @@ -1608,6 +1556,7 @@ Backup::sendAlterTrig(Signal* signal, BackupRecordPtr ptr) return; }//if ptr.p->masterData.alterTrig.tableId = RNIL; + /** * Finished with all tables */ @@ -1669,11 +1618,9 @@ Backup::alterTrigReply(Signal* signal, BackupRecordPtr ptr) return; }//if - ptr.p->masterData.gsn = 0; - if(ptr.p->checkError()){ jam(); - masterAbort(signal, ptr, true); + masterAbort(signal, ptr); return; }//if @@ -1719,11 +1666,10 @@ Backup::execWAIT_GCP_CONF(Signal* signal){ ndbrequire(ptr.p->masterRef == reference()); ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ); - ptr.p->masterData.gsn = 0; if(ptr.p->checkError()) { jam(); - masterAbort(signal, ptr, true); + masterAbort(signal, ptr); return; }//if @@ -1731,13 +1677,13 @@ Backup::execWAIT_GCP_CONF(Signal* signal){ jam(); CRASH_INSERTION((10008)); ptr.p->startGCP = gcp; - ptr.p->masterData.state.setState(SCANNING); + ptr.p->masterData.sendCounter= 0; + ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ; nextFragment(signal, ptr); } else { jam(); CRASH_INSERTION((10009)); ptr.p->stopGCP = gcp; - ptr.p->masterData.state.setState(STOPPING); sendDropTrig(signal, ptr); // regular dropping of triggers }//if } @@ -1787,6 +1733,7 @@ Backup::nextFragment(Signal* signal, BackupRecordPtr ptr) req->fragmentNo = i; req->count = 0; + ptr.p->masterData.sendCounter++; const BlockReference ref = numberToRef(BACKUP, nodeId); sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal, BackupFragmentReq::SignalLength, JBB); @@ -1824,7 +1771,7 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtr(); const Uint32 ptrI = conf->backupPtr; - const Uint32 backupId = conf->backupId; + //const Uint32 backupId = conf->backupId; const Uint32 tableId = conf->tableId; const Uint32 fragmentNo = conf->fragmentNo; const Uint32 nodeId = refToNode(signal->senderBlockRef()); @@ -1834,10 +1781,9 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING - ptr.p->noOfBytes += noOfBytes; ptr.p->noOfRecords += noOfRecords; + ptr.p->masterData.sendCounter--; TablePtr tabPtr; ndbrequire(findTable(ptr, tabPtr, tableId)); @@ -1852,17 +1798,24 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) fragPtr.p->scanned = 1; fragPtr.p->scanning = 0; - if(ptr.p->checkError()) { - jam(); - masterAbort(signal, ptr, true); - return; - }//if - if (ERROR_INSERTED(10028)) { + if (ERROR_INSERTED(10028)) + { ptr.p->errorCode = 328; - masterAbort(signal, ptr, true); - return; - }//if - nextFragment(signal, ptr); + } + + if(ptr.p->checkError()) + { + if(ptr.p->masterData.sendCounter.done()) + { + jam(); + masterAbort(signal, ptr); + return; + }//if + } + else + { + nextFragment(signal, ptr); + } } void @@ -1874,15 +1827,52 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal) BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr(); const Uint32 ptrI = ref->backupPtr; - const Uint32 backupId = ref->backupId; + //const Uint32 backupId = ref->backupId; + const Uint32 nodeId = ref->nodeId; BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING + TablePtr tabPtr; + ptr.p->tables.first(tabPtr); + for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) { + jam(); + FragmentPtr fragPtr; + Array & frags = tabPtr.p->fragments; + const Uint32 fragCount = frags.getSize(); + + for(Uint32 i = 0; ifragments.getPtr(fragPtr, i); + if(fragPtr.p->scanning != 0 && nodeId == fragPtr.p->node) + { + jam(); + ndbrequire(fragPtr.p->scanned == 0); + fragPtr.p->scanned = 1; + fragPtr.p->scanning = 0; + goto done; + } + } + } + ndbrequire(false); +done: + ptr.p->masterData.sendCounter--; ptr.p->setErrorCode(ref->errorCode); - masterAbort(signal, ptr, true); + + if(ptr.p->masterData.sendCounter.done()) + { + jam(); + masterAbort(signal, ptr); + return; + }//if + + AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); + ord->backupId = ptr.p->backupId; + ord->backupPtr = ptr.i; + ord->requestType = AbortBackupOrd::LogBufferFull; + ord->senderData= ptr.i; + execABORT_BACKUP_ORD(signal); } /***************************************************************************** @@ -1910,15 +1900,7 @@ Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr) jam(); ptr.p->masterData.dropTrig.tableId = RNIL; - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::OkToClean); - - if(ptr.p->masterData.state.getState() == STOPPING) { - jam(); - sendStopBackup(signal, ptr); - return; - }//if - ndbrequire(ptr.p->masterData.state.getState() == ABORTING); - masterSendAbortBackup(signal, ptr); + sendStopBackup(signal, ptr); }//if } @@ -2010,7 +1992,6 @@ Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr) return; }//if - ptr.p->masterData.gsn = 0; sendDropTrig(signal, ptr); // recursive next } @@ -2023,14 +2004,23 @@ void Backup::execSTOP_BACKUP_REF(Signal* signal) { jamEntry(); - ndbrequire(0); + + StopBackupRef* ref = (StopBackupRef*)signal->getDataPtr(); + const Uint32 ptrI = ref->backupPtr; + //const Uint32 backupId = ref->backupId; + const Uint32 nodeId = ref->nodeId; + + BackupRecordPtr ptr; + c_backupPool.getPtr(ptr, ptrI); + + ptr.p->setErrorCode(ref->errorCode); + stopBackupReply(signal, ptr, nodeId); } void Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr) { jam(); - ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ; StopBackupReq* stop = (StopBackupReq*)signal->getDataPtrSend(); stop->backupPtr = ptr.i; @@ -2038,8 +2028,11 @@ Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr) stop->startGCP = ptr.p->startGCP; stop->stopGCP = ptr.p->stopGCP; - sendSignalAllWait(ptr, GSN_STOP_BACKUP_REQ, signal, - StopBackupReq::SignalLength); + ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ; + ptr.p->masterData.sendCounter = ptr.p->nodes; + NodeReceiverGroup rg(BACKUP, ptr.p->nodes); + sendSignal(rg, GSN_STOP_BACKUP_REQ, signal, + StopBackupReq::SignalLength, JBB); } void @@ -2049,14 +2042,12 @@ Backup::execSTOP_BACKUP_CONF(Signal* signal) StopBackupConf* conf = (StopBackupConf*)signal->getDataPtr(); const Uint32 ptrI = conf->backupPtr; - const Uint32 backupId = conf->backupId; + //const Uint32 backupId = conf->backupId; const Uint32 nodeId = refToNode(signal->senderBlockRef()); BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - masterAbortCheck(); // macro will do return if ABORTING - ptr.p->noOfLogBytes += conf->noOfLogBytes; ptr.p->noOfLogRecords += conf->noOfLogRecords; @@ -2073,35 +2064,39 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) return; } - // ptr.p->masterData.state.setState(INITIAL); - - // send backup complete first to slaves so that they know sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete); - - BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend(); - rep->backupId = ptr.p->backupId; - rep->senderData = ptr.p->clientData; - rep->startGCP = ptr.p->startGCP; - rep->stopGCP = ptr.p->stopGCP; - rep->noOfBytes = ptr.p->noOfBytes; - rep->noOfRecords = ptr.p->noOfRecords; - rep->noOfLogBytes = ptr.p->noOfLogBytes; - rep->noOfLogRecords = ptr.p->noOfLogRecords; - rep->nodes = ptr.p->nodes; - sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal, - BackupCompleteRep::SignalLength, JBB); - - signal->theData[0] = EventReport::BackupCompleted; - signal->theData[1] = ptr.p->clientRef; - signal->theData[2] = ptr.p->backupId; - signal->theData[3] = ptr.p->startGCP; - signal->theData[4] = ptr.p->stopGCP; - signal->theData[5] = ptr.p->noOfBytes; - signal->theData[6] = ptr.p->noOfRecords; - signal->theData[7] = ptr.p->noOfLogBytes; - signal->theData[8] = ptr.p->noOfLogRecords; - ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9); - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 9+NdbNodeBitmask::Size, JBB); + + if(!ptr.p->checkError()) + { + BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend(); + rep->backupId = ptr.p->backupId; + rep->senderData = ptr.p->clientData; + rep->startGCP = ptr.p->startGCP; + rep->stopGCP = ptr.p->stopGCP; + rep->noOfBytes = ptr.p->noOfBytes; + rep->noOfRecords = ptr.p->noOfRecords; + rep->noOfLogBytes = ptr.p->noOfLogBytes; + rep->noOfLogRecords = ptr.p->noOfLogRecords; + rep->nodes = ptr.p->nodes; + sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal, + BackupCompleteRep::SignalLength, JBB); + + signal->theData[0] = EventReport::BackupCompleted; + signal->theData[1] = ptr.p->clientRef; + signal->theData[2] = ptr.p->backupId; + signal->theData[3] = ptr.p->startGCP; + signal->theData[4] = ptr.p->stopGCP; + signal->theData[5] = ptr.p->noOfBytes; + signal->theData[6] = ptr.p->noOfRecords; + signal->theData[7] = ptr.p->noOfLogBytes; + signal->theData[8] = ptr.p->noOfLogRecords; + ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9); + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 9+NdbNodeBitmask::Size, JBB); + } + else + { + masterAbort(signal, ptr); + } } /***************************************************************************** @@ -2110,199 +2105,96 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) * *****************************************************************************/ void -Backup::masterAbort(Signal* signal, BackupRecordPtr ptr, bool controlledAbort) +Backup::masterAbort(Signal* signal, BackupRecordPtr ptr) { - if(ptr.p->masterData.state.getState() == ABORTING) { -#ifdef DEBUG_ABORT - ndbout_c("---- Master already aborting"); -#endif - jam(); - return; - } jam(); #ifdef DEBUG_ABORT ndbout_c("************ masterAbort"); #endif - - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupFailure); - if (!ptr.p->checkError()) - ptr.p->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; - - const State s = ptr.p->masterData.state.getState(); - - ptr.p->masterData.state.setState(ABORTING); - - ndbrequire(s == INITIAL || - s == STARTED || - s == DEFINING || - s == DEFINED || - s == SCANNING || - s == STOPPING || - s == ABORTING); - if(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ) { + if(ptr.p->masterData.errorCode != 0) + { jam(); - DEBUG_OUT("masterAbort: gsn = GSN_UTIL_SEQUENCE_REQ"); - //------------------------------------------------------- - // We are waiting for UTIL_SEQUENCE response. We rely on - // this to arrive and check for ABORTING in response. - // No slaves are involved at this point and ABORT simply - // results in BACKUP_REF to client - //------------------------------------------------------- - /** - * Waiting for Sequence Id - * @see execUTIL_SEQUENCE_CONF - */ return; - }//if + } + + BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend(); + rep->backupId = ptr.p->backupId; + rep->senderData = ptr.p->clientData; + rep->reason = ptr.p->errorCode; + sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, + BackupAbortRep::SignalLength, JBB); - if(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ) { - jam(); - DEBUG_OUT("masterAbort: gsn = GSN_UTIL_LOCK_REQ"); - //------------------------------------------------------- - // We are waiting for UTIL_LOCK response (mutex). We rely on - // this to arrive and check for ABORTING in response. - // No slaves are involved at this point and ABORT simply - // results in BACKUP_REF to client - //------------------------------------------------------- - /** - * Waiting for lock - * @see execUTIL_LOCK_CONF - */ + signal->theData[0] = EventReport::BackupAborted; + signal->theData[1] = ptr.p->clientRef; + signal->theData[2] = ptr.p->backupId; + signal->theData[3] = ptr.p->errorCode; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB); + + ndbrequire(ptr.p->errorCode); + ptr.p->masterData.errorCode = ptr.p->errorCode; + + AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); + ord->backupId = ptr.p->backupId; + ord->backupPtr = ptr.i; + ord->senderData= ptr.i; + NodeReceiverGroup rg(BACKUP, ptr.p->nodes); + + switch(ptr.p->masterData.gsn){ + case GSN_DEFINE_BACKUP_REQ: + ord->requestType = AbortBackupOrd::BackupFailure; + sendSignal(rg, GSN_ABORT_BACKUP_ORD, signal, + AbortBackupOrd::SignalLength, JBB); return; - }//if - - /** - * Unlock mutexes only at master - */ - jam(); - Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex); - jam(); - mutex1.unlock(); // ignore response - - jam(); - Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex); - jam(); - mutex2.unlock(); // ignore response - - if (!controlledAbort) { + case GSN_CREATE_TRIG_REQ: + case GSN_START_BACKUP_REQ: + case GSN_ALTER_TRIG_REQ: + case GSN_WAIT_GCP_REQ: + case GSN_BACKUP_FRAGMENT_REQ: jam(); - if (s == DEFINING) { - jam(); -//------------------------------------------------------- -// If we are in the defining phase all work is done by -// slaves. No triggers have been allocated thus slaves -// may free all "Master" resources, let them know... -//------------------------------------------------------- - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::OkToClean); - return; - }//if - if (s == DEFINED) { - jam(); -//------------------------------------------------------- -// DEFINED is the state when triggers are created. We rely -// on that DICT will report create trigger failure in case -// of node failure. Thus no special action is needed here. -// We will check for errorCode != 0 when receiving -// replies on create trigger. -//------------------------------------------------------- - return; - }//if - if(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ) { - jam(); - DEBUG_OUT("masterAbort: gsn = GSN_WAIT_GCP_REQ"); -//------------------------------------------------------- -// We are waiting for WAIT_GCP response. We rely on -// this to arrive and check for ABORTING in response. -//------------------------------------------------------- - - /** - * Waiting for GCP - * @see execWAIT_GCP_CONF - */ - return; - }//if - - if(ptr.p->masterData.gsn == GSN_ALTER_TRIG_REQ) { - jam(); - DEBUG_OUT("masterAbort: gsn = GSN_ALTER_TRIG_REQ"); -//------------------------------------------------------- -// We are waiting for ALTER_TRIG response. We rely on -// this to arrive and check for ABORTING in response. -//------------------------------------------------------- - - /** - * All triggers haven't been created yet - */ - return; - }//if - - if(ptr.p->masterData.gsn == GSN_DROP_TRIG_REQ) { - jam(); - DEBUG_OUT("masterAbort: gsn = GSN_DROP_TRIG_REQ"); -//------------------------------------------------------- -// We are waiting for DROP_TRIG response. We rely on -// this to arrive and will continue dropping triggers -// until completed. -//------------------------------------------------------- - - /** - * I'm currently dropping the trigger - */ - return; - }//if - }//if - -//------------------------------------------------------- -// If we are waiting for START_BACKUP responses we can -// safely start dropping triggers (state == STARTED). -// We will ignore any START_BACKUP responses after this. -//------------------------------------------------------- - DEBUG_OUT("masterAbort: sendDropTrig"); - sendDropTrig(signal, ptr); // dropping due to error + ptr.p->stopGCP= ptr.p->startGCP + 1; + sendDropTrig(signal, ptr); // dropping due to error + return; + case GSN_UTIL_SEQUENCE_REQ: + case GSN_UTIL_LOCK_REQ: + case GSN_DROP_TRIG_REQ: + ndbrequire(false); + return; + case GSN_STOP_BACKUP_REQ: + return; + } } void -Backup::masterSendAbortBackup(Signal* signal, BackupRecordPtr ptr) +Backup::abort_scan(Signal * signal, BackupRecordPtr ptr) { - if (ptr.p->masterData.state.getState() != ABORTING) { - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupFailure); - ptr.p->masterData.state.setState(ABORTING); + AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); + ord->backupId = ptr.p->backupId; + ord->backupPtr = ptr.i; + ord->senderData= ptr.i; + ord->requestType = AbortBackupOrd::AbortScan; + + TablePtr tabPtr; + ptr.p->tables.first(tabPtr); + for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) { + jam(); + FragmentPtr fragPtr; + Array & frags = tabPtr.p->fragments; + const Uint32 fragCount = frags.getSize(); + + for(Uint32 i = 0; ifragments.getPtr(fragPtr, i); + const Uint32 nodeId = fragPtr.p->node; + if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) { + jam(); + + const BlockReference ref = numberToRef(BACKUP, nodeId); + sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal, + AbortBackupOrd::SignalLength, JBB); + + } + } } - const State s = ptr.p->masterData.state.getAbortState(); - - /** - * First inform to client - */ - if(s == DEFINING) { - jam(); -#ifdef DEBUG_ABORT - ndbout_c("** Abort: sending BACKUP_REF to mgmtsrvr"); -#endif - sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, - ptr.p->errorCode); - - } else { - jam(); -#ifdef DEBUG_ABORT - ndbout_c("** Abort: sending BACKUP_ABORT_REP to mgmtsrvr"); -#endif - BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend(); - rep->backupId = ptr.p->backupId; - rep->senderData = ptr.p->clientData; - rep->reason = ptr.p->errorCode; - sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, - BackupAbortRep::SignalLength, JBB); - - signal->theData[0] = EventReport::BackupAborted; - signal->theData[1] = ptr.p->clientRef; - signal->theData[2] = ptr.p->backupId; - signal->theData[3] = ptr.p->errorCode; - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB); - }//if - - // ptr.p->masterData.state.setState(INITIAL); - - sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupFailure); } /***************************************************************************** @@ -2313,26 +2205,17 @@ Backup::masterSendAbortBackup(Signal* signal, BackupRecordPtr ptr) void Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode) { - if (ptr.p->slaveState.getState() == ABORTING) { - jam(); - return; - } - ptr.p->slaveState.setState(ABORTING); - - if (errCode != 0) { - jam(); - ptr.p->setErrorCode(errCode); - }//if + ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF; + ptr.p->setErrorCode(errCode); ndbrequire(ptr.p->errorCode != 0); - + DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend(); ref->backupId = ptr.p->backupId; ref->backupPtr = ptr.i; ref->errorCode = ptr.p->errorCode; + ref->nodeId = getOwnNodeId(); sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal, DefineBackupRef::SignalLength, JBB); - - closeFiles(signal, ptr); } void @@ -2366,6 +2249,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) CRASH_INSERTION((10014)); + ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ; ptr.p->slaveState.forceState(INITIAL); ptr.p->slaveState.setState(DEFINING); ptr.p->errorCode = 0; @@ -2432,7 +2316,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) files[i].p->tableId = RNIL; files[i].p->backupPtr = ptr.i; files[i].p->filePointer = RNIL; - files[i].p->fileDone = 0; + files[i].p->fileClosing = 0; files[i].p->fileOpened = 0; files[i].p->fileRunning = 0; files[i].p->scanRunning = 0; @@ -2468,17 +2352,14 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) ptr.p->logFilePtr = files[1].i; ptr.p->dataFilePtr = files[2].i; - if (!verifyNodesAlive(ptr.p->nodes)) { + if (!verifyNodesAlive(ptr, ptr.p->nodes)) { jam(); defineBackupRef(signal, ptr, DefineBackupRef::Undefined); - // sendBackupRef(signal, ptr, - // ptr.p->errorCode?ptr.p->errorCode:BackupRef::Undefined); return; }//if if (ERROR_INSERTED(10027)) { jam(); defineBackupRef(signal, ptr, 327); - // sendBackupRef(signal, ptr, 327); return; }//if @@ -2546,8 +2427,6 @@ Backup::execLIST_TABLES_CONF(Signal* signal) return; }//if - defineSlaveAbortCheck(); - /** * All tables fetched */ @@ -2679,8 +2558,6 @@ Backup::openFilesReply(Signal* signal, }//if }//for - defineSlaveAbortCheck(); - /** * Did open succeed for all files */ @@ -2810,8 +2687,6 @@ Backup::execGET_TABINFOREF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, senderData); - defineSlaveAbortCheck(); - defineBackupRef(signal, ptr, ref->errorCode); } @@ -2833,8 +2708,6 @@ Backup::execGET_TABINFO_CONF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, senderData); - defineSlaveAbortCheck(); - SegmentedSectionPtr dictTabInfoPtr; signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO); ndbrequire(dictTabInfoPtr.sz == len); @@ -3047,8 +2920,6 @@ Backup::execDI_FCOUNTCONF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, senderData); - defineSlaveAbortCheck(); - TablePtr tabPtr; ndbrequire(findTable(ptr, tabPtr, tableId)); @@ -3127,8 +2998,6 @@ Backup::execDIGETPRIMCONF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, senderData); - defineSlaveAbortCheck(); - TablePtr tabPtr; ndbrequire(findTable(ptr, tabPtr, tableId)); @@ -3143,9 +3012,7 @@ Backup::execDIGETPRIMCONF(Signal* signal) void Backup::getFragmentInfoDone(Signal* signal, BackupRecordPtr ptr) { - // Slave must now hold on to master data until - // AbortBackupOrd::OkToClean signal - ptr.p->okToCleanMaster = false; + ptr.p->m_gsn = GSN_DEFINE_BACKUP_CONF; ptr.p->slaveState.setState(DEFINED); DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtr(); conf->backupPtr = ptr.i; @@ -3169,16 +3036,15 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) StartBackupReq* req = (StartBackupReq*)signal->getDataPtr(); const Uint32 ptrI = req->backupPtr; - const Uint32 backupId = req->backupId; + //const Uint32 backupId = req->backupId; const Uint32 signalNo = req->signalNo; - + BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - - slaveAbortCheck(); // macro will do return if ABORTING ptr.p->slaveState.setState(STARTED); - + ptr.p->m_gsn = GSN_START_BACKUP_REQ; + for(Uint32 i = 0; inoOfTableTriggers; i++) { jam(); TablePtr tabPtr; @@ -3191,11 +3057,13 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) TriggerPtr trigPtr; if(!ptr.p->triggers.seizeId(trigPtr, triggerId)) { jam(); + ptr.p->m_gsn = GSN_START_BACKUP_REF; StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend(); ref->backupPtr = ptr.i; ref->backupId = ptr.p->backupId; ref->signalNo = signalNo; ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord; + ref->nodeId = getOwnNodeId(); sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal, StartBackupRef::SignalLength, JBB); return; @@ -3233,6 +3101,7 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) }//if }//for + ptr.p->m_gsn = GSN_START_BACKUP_CONF; StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend(); conf->backupPtr = ptr.i; conf->backupId = ptr.p->backupId; @@ -3255,7 +3124,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) CRASH_INSERTION((10016)); const Uint32 ptrI = req->backupPtr; - const Uint32 backupId = req->backupId; + //const Uint32 backupId = req->backupId; const Uint32 tableId = req->tableId; const Uint32 fragNo = req->fragmentNo; const Uint32 count = req->count; @@ -3266,10 +3135,9 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); - slaveAbortCheck(); // macro will do return if ABORTING - ptr.p->slaveState.setState(SCANNING); - + ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REQ; + /** * Get file */ @@ -3280,7 +3148,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) ndbrequire(filePtr.p->fileOpened == 1); ndbrequire(filePtr.p->fileRunning == 1); ndbrequire(filePtr.p->scanRunning == 0); - ndbrequire(filePtr.p->fileDone == 0); + ndbrequire(filePtr.p->fileClosing == 0); /** * Get table @@ -3350,7 +3218,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) req->transId1 = 0; req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8); req->clientOpPtr= filePtr.i; - req->batch_size_rows= 16; + req->batch_size_rows= parallelism; req->batch_size_bytes= 0; sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal, ScanFragReq::SignalLength, JBB); @@ -3572,6 +3440,13 @@ Backup::OperationRecord::newScan() return false; } +bool +Backup::OperationRecord::closeScan() +{ + opNoDone = opNoConf = opLen = 0; + return true; +} + bool Backup::OperationRecord::scanConf(Uint32 noOfOps, Uint32 total_len) { @@ -3600,11 +3475,9 @@ Backup::execSCAN_FRAGREF(Signal* signal) c_backupFilePool.getPtr(filePtr, filePtrI); filePtr.p->errorCode = ref->errorCode; + filePtr.p->scanRunning = 0; - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, filePtr.p->backupPtr); - - abortFile(signal, ptr, filePtr); + backupFragmentRef(signal, filePtr); } void @@ -3639,9 +3512,11 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr) { jam(); - if(filePtr.p->errorCode != 0){ + if(filePtr.p->errorCode != 0) + { jam(); - abortFileHook(signal, filePtr, true); // Scan completed + filePtr.p->scanRunning = 0; + backupFragmentRef(signal, filePtr); // Scan completed return; }//if @@ -3669,20 +3544,51 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr) sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal, BackupFragmentConf::SignalLength, JBB); + ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_CONF; ptr.p->slaveState.setState(STARTED); return; } + +void +Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr) +{ + BackupRecordPtr ptr; + c_backupPool.getPtr(ptr, filePtr.p->backupPtr); + + ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF; + + BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtrSend(); + ref->backupId = ptr.p->backupId; + ref->backupPtr = ptr.i; + ref->nodeId = getOwnNodeId(); + ref->errorCode = ptr.p->errorCode; + sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal, + BackupFragmentRef::SignalLength, JBB); +} void Backup::checkScan(Signal* signal, BackupFilePtr filePtr) { - if(filePtr.p->errorCode != 0){ + OperationRecord & op = filePtr.p->operation; + + if(filePtr.p->errorCode != 0) + { jam(); - abortFileHook(signal, filePtr, false); // Scan not completed + + /** + * Close scan + */ + op.closeScan(); + ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend(); + req->senderData = filePtr.i; + req->closeFlag = 1; + req->transId1 = 0; + req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8); + sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); return; }//if - - OperationRecord & op = filePtr.p->operation; + if(op.newScan()) { jam(); @@ -3693,8 +3599,28 @@ Backup::checkScan(Signal* signal, BackupFilePtr filePtr) req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8); req->batch_size_rows= 16; req->batch_size_bytes= 0; - sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, - ScanFragNextReq::SignalLength, JBB); + if(ERROR_INSERTED(10032)) + sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, + 100, ScanFragNextReq::SignalLength); + else if(ERROR_INSERTED(10033)) + { + SET_ERROR_INSERT_VALUE(10032); + sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, + 10000, ScanFragNextReq::SignalLength); + + BackupRecordPtr ptr; + c_backupPool.getPtr(ptr, filePtr.p->backupPtr); + AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); + ord->backupId = ptr.p->backupId; + ord->backupPtr = ptr.i; + ord->requestType = AbortBackupOrd::FileOrScanError; + ord->senderData= ptr.i; + sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, + AbortBackupOrd::SignalLength, JBB); + } + else + sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); return; }//if @@ -3718,11 +3644,8 @@ Backup::execFSAPPENDREF(Signal* signal) filePtr.p->fileRunning = 0; filePtr.p->errorCode = errCode; - - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, filePtr.p->backupPtr); - - abortFile(signal, ptr, filePtr); + + checkFile(signal, filePtr); } void @@ -3738,12 +3661,6 @@ Backup::execFSAPPENDCONF(Signal* signal) BackupFilePtr filePtr; c_backupFilePool.getPtr(filePtr, filePtrI); - - if (ERROR_INSERTED(10029)) { - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, filePtr.p->backupPtr); - abortFile(signal, ptr, filePtr); - }//if OperationRecord & op = filePtr.p->operation; @@ -3761,30 +3678,25 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) #endif OperationRecord & op = filePtr.p->operation; - + Uint32 * tmp, sz; bool eof; - if(op.dataBuffer.getReadPtr(&tmp, &sz, &eof)) { + if(op.dataBuffer.getReadPtr(&tmp, &sz, &eof)) + { jam(); - if(filePtr.p->errorCode == 0) { - jam(); - FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend(); - req->filePointer = filePtr.p->filePointer; - req->userPointer = filePtr.i; - req->userReference = reference(); - req->varIndex = 0; - req->offset = tmp - c_startOfPages; - req->size = sz; - - sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, - FsAppendReq::SignalLength, JBA); - return; - } else { - jam(); - if (filePtr.p->scanRunning == 1) - eof = false; - }//if - }//if + jam(); + FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend(); + req->filePointer = filePtr.p->filePointer; + req->userPointer = filePtr.i; + req->userReference = reference(); + req->varIndex = 0; + req->offset = tmp - c_startOfPages; + req->size = sz; + + sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, + FsAppendReq::SignalLength, JBA); + return; + } if(!eof) { jam(); @@ -3794,9 +3706,7 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) return; }//if - ndbrequire(filePtr.p->fileDone == 1); - - if(sz > 0 && filePtr.p->errorCode == 0) { + if(sz > 0) { jam(); FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend(); req->filePointer = filePtr.p->filePointer; @@ -3812,6 +3722,7 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) }//if filePtr.p->fileRunning = 0; + filePtr.p->fileClosing = 1; FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend(); req->filePointer = filePtr.p->filePointer; @@ -3819,64 +3730,11 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) req->userReference = reference(); req->fileFlag = 0; #ifdef DEBUG_ABORT - ndbout_c("***** FSCLOSEREQ filePtr.i = %u", filePtr.i); + ndbout_c("***** a FSCLOSEREQ filePtr.i = %u", filePtr.i); #endif sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA); } -void -Backup::abortFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr) -{ - jam(); - - if(ptr.p->slaveState.getState() != ABORTING) { - /** - * Inform master of failure - */ - jam(); - ptr.p->slaveState.setState(ABORTING); - ptr.p->setErrorCode(AbortBackupOrd::FileOrScanError); - sendAbortBackupOrdSlave(signal, ptr, AbortBackupOrd::FileOrScanError); - return; - }//if - - - for(ptr.p->files.first(filePtr); - filePtr.i!=RNIL; - ptr.p->files.next(filePtr)){ - jam(); - filePtr.p->errorCode = 1; - }//for - - closeFiles(signal, ptr); -} - -void -Backup::abortFileHook(Signal* signal, BackupFilePtr filePtr, bool scanComplete) -{ - jam(); - - if(!scanComplete) { - jam(); - - ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend(); - req->senderData = filePtr.i; - req->closeFlag = 1; - req->transId1 = 0; - req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8); - sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, - ScanFragNextReq::SignalLength, JBB); - return; - }//if - - filePtr.p->scanRunning = 0; - - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, filePtr.p->backupPtr); - - filePtr.i = RNIL; - abortFile(signal, ptr, filePtr); -} /**************************************************************************** * @@ -3953,27 +3811,30 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { }//if BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry; - if(logEntry == 0) { + if(logEntry == 0) + { jam(); Uint32 * dst; FsBuffer & buf = trigPtr.p->operation->dataBuffer; ndbrequire(trigPtr.p->maxRecordSize <= buf.getMaxWrite()); - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); - if(!buf.getWritePtr(&dst, trigPtr.p->maxRecordSize)) { + if(ERROR_INSERTED(10030) || + !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize)) + { jam(); + BackupRecordPtr ptr; + c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull; - sendAbortBackupOrdSlave(signal, ptr, AbortBackupOrd::LogBufferFull); + AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); + ord->backupId = ptr.p->backupId; + ord->backupPtr = ptr.i; + ord->requestType = AbortBackupOrd::LogBufferFull; + ord->senderData= ptr.i; + sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, + AbortBackupOrd::SignalLength, JBB); return; }//if - if(trigPtr.p->operation->noOfBytes > 123 && ERROR_INSERTED(10030)) { - jam(); - trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull; - sendAbortBackupOrdSlave(signal, ptr, AbortBackupOrd::LogBufferFull); - return; - }//if - + logEntry = (BackupFormat::LogFile::LogEntry *)dst; trigPtr.p->logEntry = logEntry; logEntry->Length = 0; @@ -4015,9 +3876,10 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); - if(gci != ptr.p->currGCP) { + if(gci != ptr.p->currGCP) + { jam(); - + trigPtr.p->logEntry->TriggerEvent = htonl(trigPtr.p->event | 0x10000); trigPtr.p->logEntry->Data[len] = htonl(gci); len ++; @@ -4035,20 +3897,6 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) trigPtr.p->operation->noOfRecords += 1; } -void -Backup::sendAbortBackupOrdSlave(Signal* signal, BackupRecordPtr ptr, - Uint32 requestType) -{ - jam(); - AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); - ord->backupId = ptr.p->backupId; - ord->backupPtr = ptr.i; - ord->requestType = requestType; - ord->senderData= ptr.i; - sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, - AbortBackupOrd::SignalLength, JBB); -} - void Backup::sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr, Uint32 requestType) @@ -4085,7 +3933,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) CRASH_INSERTION((10020)); const Uint32 ptrI = req->backupPtr; - const Uint32 backupId = req->backupId; + //const Uint32 backupId = req->backupId; const Uint32 startGCP = req->startGCP; const Uint32 stopGCP = req->stopGCP; @@ -4101,7 +3949,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) c_backupPool.getPtr(ptr, ptrI); ptr.p->slaveState.setState(STOPPING); - slaveAbortCheck(); // macro will do return if ABORTING + ptr.p->m_gsn = GSN_STOP_BACKUP_REQ; /** * Insert footers @@ -4140,12 +3988,6 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) void Backup::closeFiles(Signal* sig, BackupRecordPtr ptr) { - if (ptr.p->closingFiles) { - jam(); - return; - } - ptr.p->closingFiles = true; - /** * Close all files */ @@ -4161,12 +4003,12 @@ Backup::closeFiles(Signal* sig, BackupRecordPtr ptr) jam(); openCount++; - if(filePtr.p->fileDone == 1){ + if(filePtr.p->fileClosing == 1){ jam(); continue; }//if - filePtr.p->fileDone = 1; + filePtr.p->fileClosing = 1; if(filePtr.p->fileRunning == 1){ jam(); @@ -4183,7 +4025,7 @@ Backup::closeFiles(Signal* sig, BackupRecordPtr ptr) req->userReference = reference(); req->fileFlag = 0; #ifdef DEBUG_ABORT - ndbout_c("***** FSCLOSEREQ filePtr.i = %u", filePtr.i); + ndbout_c("***** b FSCLOSEREQ filePtr.i = %u", filePtr.i); #endif sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, sig, FsCloseReq::SignalLength, JBA); @@ -4210,11 +4052,6 @@ Backup::execFSCLOSEREF(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); - /** - * This should only happen during abort of backup - */ - ndbrequire(ptr.p->slaveState.getState() == ABORTING); - filePtr.p->fileOpened = 1; FsConf * conf = (FsConf*)signal->getDataPtr(); conf->userPointer = filePtrI; @@ -4237,7 +4074,7 @@ Backup::execFSCLOSECONF(Signal* signal) ndbout_c("***** FSCLOSECONF filePtrI = %u", filePtrI); #endif - ndbrequire(filePtr.p->fileDone == 1); + ndbrequire(filePtr.p->fileClosing == 1); ndbrequire(filePtr.p->fileOpened == 1); ndbrequire(filePtr.p->fileRunning == 0); ndbrequire(filePtr.p->scanRunning == 0); @@ -4265,25 +4102,20 @@ Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr) { jam(); - if(ptr.p->slaveState.getState() == STOPPING) { - jam(); - BackupFilePtr filePtr; - ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr); - - StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend(); - conf->backupId = ptr.p->backupId; - conf->backupPtr = ptr.i; - conf->noOfLogBytes = filePtr.p->operation.noOfBytes; - conf->noOfLogRecords = filePtr.p->operation.noOfRecords; - sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal, - StopBackupConf::SignalLength, JBB); - - ptr.p->slaveState.setState(CLEANING); - return; - }//if + jam(); + BackupFilePtr filePtr; + ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr); - ndbrequire(ptr.p->slaveState.getState() == ABORTING); - removeBackup(signal, ptr); + StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend(); + conf->backupId = ptr.p->backupId; + conf->backupPtr = ptr.i; + conf->noOfLogBytes = filePtr.p->operation.noOfBytes; + conf->noOfLogRecords = filePtr.p->operation.noOfRecords; + sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal, + StopBackupConf::SignalLength, JBB); + + ptr.p->m_gsn = GSN_STOP_BACKUP_CONF; + ptr.p->slaveState.setState(CLEANING); } /***************************************************************************** @@ -4291,57 +4123,6 @@ Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr) * Slave functionallity: Abort backup * *****************************************************************************/ -void -Backup::removeBackup(Signal* signal, BackupRecordPtr ptr) -{ - jam(); - - FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend(); - req->userReference = reference(); - req->userPointer = ptr.i; - req->directory = 1; - req->ownDirectory = 1; - FsOpenReq::setVersion(req->fileNumber, 2); - FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL); - FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId); - FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId()); - sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, - FsRemoveReq::SignalLength, JBA); -} - -void -Backup::execFSREMOVEREF(Signal* signal) -{ - jamEntry(); - ndbrequire(0); -} - -void -Backup::execFSREMOVECONF(Signal* signal){ - jamEntry(); - - FsConf * conf = (FsConf*)signal->getDataPtr(); - const Uint32 ptrI = conf->userPointer; - - /** - * Get backup record - */ - BackupRecordPtr ptr; - c_backupPool.getPtr(ptr, ptrI); - - ndbrequire(ptr.p->slaveState.getState() == ABORTING); - if (ptr.p->masterRef == reference()) { - if (ptr.p->masterData.state.getAbortState() == DEFINING) { - jam(); - sendBackupRef(signal, ptr, ptr.p->errorCode); - return; - } else { - jam(); - }//if - }//if - cleanupSlaveResources(ptr); -} - /***************************************************************************** * * Slave functionallity: Abort backup @@ -4394,8 +4175,7 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) if (c_backupPool.findId(senderData)) { jam(); c_backupPool.getPtr(ptr, senderData); - } else { // TODO might be abort sent to not master, - // or master aborting too early + } else { jam(); #ifdef DEBUG_ABORT ndbout_c("Backup: abort request type=%u on id=%u,%u not found", @@ -4405,15 +4185,15 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) } }//if + ptr.p->m_gsn = GSN_ABORT_BACKUP_ORD; const bool isCoordinator = (ptr.p->masterRef == reference()); - + bool ok = false; switch(requestType){ /** * Requests sent to master */ - case AbortBackupOrd::ClientAbort: jam(); // fall through @@ -4422,113 +4202,61 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) // fall through case AbortBackupOrd::FileOrScanError: jam(); - if(ptr.p->masterData.state.getState() == ABORTING) { -#ifdef DEBUG_ABORT - ndbout_c("---- Already aborting"); -#endif - jam(); - return; - } + ndbrequire(isCoordinator); ptr.p->setErrorCode(requestType); - ndbrequire(isCoordinator); // Sent from slave to coordinator - masterAbort(signal, ptr, false); + if(ptr.p->masterData.gsn == GSN_BACKUP_FRAGMENT_REQ) + { + /** + * Only scans are actively aborted + */ + abort_scan(signal, ptr); + } return; - - /** - * Info sent to slave - */ - - case AbortBackupOrd::OkToClean: - jam(); - cleanupMasterResources(ptr); - return; - + /** * Requests sent to slave */ - + case AbortBackupOrd::AbortScan: + jam(); + ptr.p->setErrorCode(requestType); + return; + case AbortBackupOrd::BackupComplete: jam(); - if (ptr.p->slaveState.getState() == CLEANING) { // TODO what if state is - // not CLEANING? - jam(); - cleanupSlaveResources(ptr); - }//if + cleanup(signal, ptr); return; - break; - case AbortBackupOrd::BackupFailureDueToNodeFail: - jam(); - ok = true; - if (ptr.p->errorCode != 0) - ptr.p->setErrorCode(requestType); - break; case AbortBackupOrd::BackupFailure: - jam(); - ok = true; - break; + case AbortBackupOrd::BackupFailureDueToNodeFail: + case AbortBackupOrd::OkToClean: + case AbortBackupOrd::IncompatibleVersions: +#ifndef VM_TRACE + default: +#endif + ptr.p->setErrorCode(requestType); + ok= true; } ndbrequire(ok); - /** - * Slave abort - */ - slaveAbort(signal, ptr); -} - -void -Backup::slaveAbort(Signal* signal, BackupRecordPtr ptr) -{ - if(ptr.p->slaveState.getState() == ABORTING) { -#ifdef DEBUG_ABORT - ndbout_c("---- Slave already aborting"); -#endif - jam(); - return; + Uint32 ref= ptr.p->masterRef; + ptr.p->masterRef = reference(); + ptr.p->nodes.clear(); + ptr.p->nodes.set(getOwnNodeId()); + + if(ref == reference()) + { + ptr.p->stopGCP= ptr.p->startGCP + 1; + sendDropTrig(signal, ptr); } -#ifdef DEBUG_ABORT - ndbout_c("************* slaveAbort"); -#endif - - State slaveState = ptr.p->slaveState.getState(); - ptr.p->slaveState.setState(ABORTING); - switch(slaveState) { - case DEFINING: - jam(); - return; -//------------------------------------------ -// Will watch for the abort at various places -// in the defining phase. -//------------------------------------------ - case ABORTING: - jam(); - //Fall through - case DEFINED: - jam(); - //Fall through - case STOPPING: - jam(); + else + { + ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ; + ptr.p->masterData.sendCounter.clearWaitingFor(); + ptr.p->masterData.sendCounter.setWaitingFor(getOwnNodeId()); closeFiles(signal, ptr); - return; - case STARTED: - jam(); - //Fall through - case SCANNING: - jam(); - BackupFilePtr filePtr; - filePtr.i = RNIL; - abortFile(signal, ptr, filePtr); - return; - case CLEANING: - jam(); - cleanupSlaveResources(ptr); - return; - case INITIAL: - jam(); - ndbrequire(false); - return; } } + void Backup::dumpUsedResources() { @@ -4576,12 +4304,8 @@ Backup::dumpUsedResources() } void -Backup::cleanupMasterResources(BackupRecordPtr ptr) +Backup::cleanup(Signal* signal, BackupRecordPtr ptr) { -#ifdef DEBUG_ABORT - ndbout_c("******** Cleanup Master Resources *********"); - ndbout_c("backupId = %u, errorCode = %u", ptr.p->backupId, ptr.p->errorCode); -#endif TablePtr tabPtr; for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;ptr.p->tables.next(tabPtr)) @@ -4601,20 +4325,6 @@ Backup::cleanupMasterResources(BackupRecordPtr ptr) tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID; }//for }//for - ptr.p->tables.release(); - ptr.p->triggers.release(); - ptr.p->okToCleanMaster = true; - - cleanupFinalResources(ptr); -} - -void -Backup::cleanupSlaveResources(BackupRecordPtr ptr) -{ -#ifdef DEBUG_ABORT - ndbout_c("******** Clean Up Slave Resources*********"); - ndbout_c("backupId = %u, errorCode = %u", ptr.p->backupId, ptr.p->errorCode); -#endif BackupFilePtr filePtr; for(ptr.p->files.first(filePtr); @@ -4626,35 +4336,65 @@ Backup::cleanupSlaveResources(BackupRecordPtr ptr) ndbrequire(filePtr.p->scanRunning == 0); filePtr.p->pages.release(); }//for - ptr.p->files.release(); - cleanupFinalResources(ptr); + ptr.p->files.release(); + ptr.p->tables.release(); + ptr.p->triggers.release(); + + ptr.p->tables.release(); + ptr.p->triggers.release(); + ptr.p->pages.release(); + ptr.p->backupId = ~0; + + if(ptr.p->checkError()) + removeBackup(signal, ptr); + else + c_backups.release(ptr); +} + + +void +Backup::removeBackup(Signal* signal, BackupRecordPtr ptr) +{ + jam(); + + FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend(); + req->userReference = reference(); + req->userPointer = ptr.i; + req->directory = 1; + req->ownDirectory = 1; + FsOpenReq::setVersion(req->fileNumber, 2); + FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL); + FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId); + FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId()); + sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, + FsRemoveReq::SignalLength, JBA); } void -Backup::cleanupFinalResources(BackupRecordPtr ptr) +Backup::execFSREMOVEREF(Signal* signal) { -#ifdef DEBUG_ABORT - ndbout_c("******** Clean Up Final Resources*********"); - ndbout_c("backupId = %u, errorCode = %u", ptr.p->backupId, ptr.p->errorCode); -#endif + jamEntry(); + FsRef * ref = (FsRef*)signal->getDataPtr(); + const Uint32 ptrI = ref->userPointer; - // if (!ptr.p->tables.empty() || !ptr.p->files.empty()) { - if (!ptr.p->okToCleanMaster || !ptr.p->files.empty()) { - jam(); -#ifdef DEBUG_ABORT - ndbout_c("******** Waiting to do final cleanup"); -#endif - return; - } - ptr.p->pages.release(); - ptr.p->masterData.state.setState(INITIAL); - ptr.p->slaveState.setState(INITIAL); - ptr.p->backupId = 0; - - ptr.p->closingFiles = false; - ptr.p->okToCleanMaster = true; - - c_backups.release(ptr); - // ndbrequire(false); + FsConf * conf = (FsConf*)signal->getDataPtr(); + conf->userPointer = ptrI; + execFSREMOVECONF(signal); } + +void +Backup::execFSREMOVECONF(Signal* signal){ + jamEntry(); + + FsConf * conf = (FsConf*)signal->getDataPtr(); + const Uint32 ptrI = conf->userPointer; + + /** + * Get backup record + */ + BackupRecordPtr ptr; + c_backupPool.getPtr(ptr, ptrI); + c_backups.release(ptr); +} + diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp index 1a5d6c7a925..7bcea5655b4 100644 --- a/ndb/src/kernel/blocks/backup/Backup.hpp +++ b/ndb/src/kernel/blocks/backup/Backup.hpp @@ -232,6 +232,7 @@ public: */ bool newScan(); bool scanConf(Uint32 noOfOps, Uint32 opLen); + bool closeScan(); /** * Per record @@ -330,7 +331,7 @@ public: Uint8 fileOpened; Uint8 fileRunning; - Uint8 fileDone; + Uint8 fileClosing; Uint8 scanRunning; }; typedef Ptr BackupFilePtr; @@ -403,13 +404,11 @@ public: ArrayPool & trp) : slaveState(b, validSlaveTransitions, validSlaveTransitionsCount,1) , tables(tp), triggers(trp), files(bp), pages(pp) - , masterData(b, validMasterTransitions, validMasterTransitionsCount) - , backup(b) - { - closingFiles = false; - okToCleanMaster = true; - } + , masterData(b), backup(b) + { + } + Uint32 m_gsn; CompoundState slaveState; Uint32 clientRef; @@ -420,9 +419,6 @@ public: Uint32 errorCode; NdbNodeBitmask nodes; - bool okToCleanMaster; - bool closingFiles; - Uint64 noOfBytes; Uint64 noOfRecords; Uint64 noOfLogBytes; @@ -444,15 +440,13 @@ public: SimpleProperties props;// Used for (un)packing backup request struct MasterData { - MasterData(Backup & b, const State valid[], Uint32 count) - : state(b, valid, count, 0) - { - } + MasterData(Backup & b) + { + } MutexHandle2 m_defineBackupMutex; MutexHandle2 m_dictCommitTableMutex; Uint32 gsn; - CompoundState state; SignalCounter sendCounter; Uint32 errorCode; struct { @@ -557,7 +551,8 @@ public: void stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId); void defineBackupRef(Signal*, BackupRecordPtr, Uint32 errCode = 0); - + void backupFragmentRef(Signal * signal, BackupFilePtr filePtr); + void nextFragment(Signal*, BackupRecordPtr); void sendCreateTrig(Signal*, BackupRecordPtr ptr, TablePtr tabPtr); @@ -578,14 +573,14 @@ public: void sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr, Uint32 errCode); void sendAbortBackupOrdSlave(Signal* signal, BackupRecordPtr ptr, Uint32 errCode); - void masterAbort(Signal*, BackupRecordPtr ptr, bool controlledAbort); + void masterAbort(Signal*, BackupRecordPtr ptr); void masterSendAbortBackup(Signal*, BackupRecordPtr ptr); void slaveAbort(Signal*, BackupRecordPtr ptr); void abortFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr); void abortFileHook(Signal* signal, BackupFilePtr filePtr, bool scanDone); - bool verifyNodesAlive(const NdbNodeBitmask& aNodeBitMask); + bool verifyNodesAlive(BackupRecordPtr, const NdbNodeBitmask& aNodeBitMask); bool checkAbort(BackupRecordPtr ptr); void checkNodeFail(Signal* signal, BackupRecordPtr ptr, @@ -603,9 +598,8 @@ public: void sendBackupRef(BlockReference ref, Signal *signal, Uint32 senderData, Uint32 errorCode); void dumpUsedResources(); - void cleanupMasterResources(BackupRecordPtr ptr); - void cleanupSlaveResources(BackupRecordPtr ptr); - void cleanupFinalResources(BackupRecordPtr ptr); + void cleanup(Signal*, BackupRecordPtr ptr); + void abort_scan(Signal*, BackupRecordPtr ptr); void removeBackup(Signal*, BackupRecordPtr ptr); void sendSTTORRY(Signal*); diff --git a/ndb/src/kernel/blocks/backup/Backup.txt b/ndb/src/kernel/blocks/backup/Backup.txt index ee5e02bb549..73942c6ebdc 100644 --- a/ndb/src/kernel/blocks/backup/Backup.txt +++ b/ndb/src/kernel/blocks/backup/Backup.txt @@ -341,3 +341,28 @@ start backup (ERROR_INSERTED(10022))) { if (ERROR_INSERTED(10029)) { if(trigPtr.p->operation->noOfBytes > 123 && ERROR_INSERTED(10030)) { + +----- XXX --- + +DEFINE_BACKUP_REF -> + ABORT_BACKUP_ORD(no reply) when all DEFINE_BACKUP replies has arrived + +START_BACKUP_REF + ABORT_BACKUP_ORD(no reply) when all START_BACKUP_ replies has arrived + +BACKUP_FRAGMENT_REF + ABORT_BACKUP_ORD(reply) directly to all nodes running BACKUP_FRAGMENT + + When all nodes has replied BACKUP_FRAGMENT + ABORT_BACKUP_ORD(no reply) + +STOP_BACKUP_REF + ABORT_BACKUP_ORD(no reply) when all STOP_BACKUP_ replies has arrived + +NF_COMPLETE_REP + slave dies + master sends OUTSTANDING_REF to self + slave does nothing + + master dies + slave elects self as master and sets only itself as participant diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp index 08fa089a9c0..eae72f43db5 100644 --- a/ndb/src/kernel/blocks/backup/BackupInit.cpp +++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp @@ -175,7 +175,7 @@ Backup::Backup(const Configuration & conf) : addRecSignal(GSN_START_BACKUP_CONF, &Backup::execSTART_BACKUP_CONF); addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Backup::execBACKUP_FRAGMENT_REQ); - //addRecSignal(GSN_BACKUP_FRAGMENT_REF, &Backup::execBACKUP_FRAGMENT_REF); + addRecSignal(GSN_BACKUP_FRAGMENT_REF, &Backup::execBACKUP_FRAGMENT_REF); addRecSignal(GSN_BACKUP_FRAGMENT_CONF, &Backup::execBACKUP_FRAGMENT_CONF); addRecSignal(GSN_STOP_BACKUP_REQ, &Backup::execSTOP_BACKUP_REQ); diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index dfae180ae71..0274ef4af3e 100644 --- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -126,6 +126,7 @@ Cmvmi::Cmvmi(const Configuration & conf) : } setNodeInfo(getOwnNodeId()).m_connected = true; + setNodeInfo(getOwnNodeId()).m_version = ndbGetOwnVersion(); } Cmvmi::~Cmvmi() diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 68106c4689d..a8931fb32ea 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -1565,9 +1565,9 @@ ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed, { // start backup can take some time, set timeout high Uint64 old_timeout= handle->read_timeout; if (wait_completed == 2) - handle->read_timeout= 30*60*1000; // 30 minutes + handle->read_timeout= 48*60*60*1000; // 48 hours else if (wait_completed == 1) - handle->read_timeout= 5*60*1000; // 5 minutes + handle->read_timeout= 10*60*1000; // 10 minutes reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args); handle->read_timeout= old_timeout; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index fb05e57e138..ceaedc9955b 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -791,7 +791,7 @@ MgmtSrvr::restartNode(int processId, bool nostart, result = sendSignal(processId, NO_WAIT, signal, true); } - if (result == -1) { + if (result == -1 && theWaitState != WAIT_NODEFAILURE) { m_stopRec.inUse = false; return SEND_OR_RECEIVE_FAILED; } @@ -1920,6 +1920,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) #ifdef VM_TRACE ndbout_c("I'm not master resending to %d", aNodeId); #endif + theWaitNode= aNodeId; NdbApiSignal aSignal(_ownReference); BackupReq* req = CAST_PTR(BackupReq, aSignal.getDataPtrSend()); aSignal.set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, @@ -1947,6 +1948,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) event.Event = BackupEvent::BackupAborted; event.Aborted.Reason = rep->reason; event.Aborted.BackupId = rep->backupId; + event.Aborted.ErrorCode = rep->reason; backupCallback(event); } break; @@ -2076,6 +2078,13 @@ MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete) handleStopReply(nodeId, 0); DBUG_VOID_RETURN; } + + if(theWaitNode == nodeId && + theWaitState != NO_WAIT && theWaitState != WAIT_STOP) + { + theWaitState = WAIT_NODEFAILURE; + NdbCondition_Signal(theMgmtWaitForResponseCondPtr); + } } eventReport(_ownNodeId, theData); @@ -2427,7 +2436,7 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) int result; if (waitCompleted == 2) { result = sendRecSignal(nodeId, WAIT_BACKUP_COMPLETED, - signal, true, 30*60*1000 /*30 secs*/); + signal, true, 48*60*60*1000 /* 48 hours */); } else if (waitCompleted == 1) { result = sendRecSignal(nodeId, WAIT_BACKUP_STARTED, @@ -2456,22 +2465,6 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) return -1; break; } - } else { - switch(m_lastBackupEvent.Event){ - case BackupEvent::BackupCompleted: - backupId = m_lastBackupEvent.Completed.BackupId; - break; - case BackupEvent::BackupStarted: - backupId = m_lastBackupEvent.Started.BackupId; - break; - case BackupEvent::BackupFailedToStart: - return m_lastBackupEvent.FailedToStart.ErrorCode; - case BackupEvent::BackupAborted: - return m_lastBackupEvent.Aborted.ErrorCode; - default: - return -1; - break; - } } return 0; diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index a05b29b7f31..ce78983b3c3 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -611,7 +611,8 @@ private: WAIT_STOP, WAIT_BACKUP_STARTED, WAIT_BACKUP_COMPLETED, - WAIT_VERSION + WAIT_VERSION, + WAIT_NODEFAILURE }; /** @@ -695,6 +696,7 @@ private: NdbApiSignal* theSignalIdleList; // List of unused signals + Uint32 theWaitNode; WaitSignalType theWaitState; // State denoting a set of signals we accept to recieve. diff --git a/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp b/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp index 2126c9d358d..f93948abc75 100644 --- a/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp +++ b/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp @@ -108,6 +108,7 @@ MgmtSrvr::sendRecSignal(Uint16 aNodeId, return -1; } theWaitState = aWaitState; + theWaitNode = aNodeId; return receiveOptimisedResponse(waitTime); } @@ -119,11 +120,12 @@ MgmtSrvr::receiveOptimisedResponse(int waitTime) theFacade->checkForceSend(_blockNumber); NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime; - while (theWaitState != NO_WAIT && waitTime > 0) { + while (theWaitState != NO_WAIT && theWaitState != WAIT_NODEFAILURE + && waitTime > 0) { NdbCondition_WaitTimeout(theMgmtWaitForResponseCondPtr, theFacade->theMutexPtr, waitTime); - if(theWaitState == NO_WAIT) + if(theWaitState == NO_WAIT || theWaitState == WAIT_NODEFAILURE) break; waitTime = (maxTime - NdbTick_CurrentMillisecond()); }//while diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index d4ad9cd6f1c..484e91f2977 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -345,7 +345,7 @@ ErrorBundle ErrorCodes[] = { { 1325, IE, "File or scan error" }, { 1326, IE, "Backup abortet due to node failure" }, { 1327, IE, "1327" }, - + { 1340, IE, "Backup undefined error" }, { 1342, AE, "Backup failed to allocate buffers (check configuration)" }, { 1343, AE, "Backup failed to setup fs buffers (check configuration)" }, @@ -355,7 +355,8 @@ ErrorBundle ErrorCodes[] = { { 1347, AE, "Backup failed to allocate table memory (check configuration)" }, { 1348, AE, "Backup failed to allocate file record (check configuration)" }, { 1349, AE, "Backup failed to allocate attribute record (check configuration)" }, - + { 1329, AE, "Backup during software upgrade not supported" }, + /** * Still uncategorized */ diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp index 77b9d0a4baa..bea5d5307e2 100644 --- a/ndb/test/ndbapi/testBackup.cpp +++ b/ndb/test/ndbapi/testBackup.cpp @@ -74,20 +74,20 @@ int runAbort(NDBT_Context* ctx, NDBT_Step* step){ if (testMaster) { if (testSlave) { - if (backup.NFMasterAsSlave(restarter) == -1){ + if (backup.NFMasterAsSlave(restarter) != NDBT_OK){ return NDBT_FAILED; } } else { - if (backup.NFMaster(restarter) == -1){ + if (backup.NFMaster(restarter) != NDBT_OK){ return NDBT_FAILED; } } } else { - if (backup.NFSlave(restarter) == -1){ + if (backup.NFSlave(restarter) != NDBT_OK){ return NDBT_FAILED; } } - + return NDBT_OK; } @@ -108,16 +108,16 @@ int runFail(NDBT_Context* ctx, NDBT_Step* step){ if (testMaster) { if (testSlave) { - if (backup.FailMasterAsSlave(restarter) == -1){ + if (backup.FailMasterAsSlave(restarter) != NDBT_OK){ return NDBT_FAILED; } } else { - if (backup.FailMaster(restarter) == -1){ + if (backup.FailMaster(restarter) != NDBT_OK){ return NDBT_FAILED; } } } else { - if (backup.FailSlave(restarter) == -1){ + if (backup.FailSlave(restarter) != NDBT_OK){ return NDBT_FAILED; } } diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 453fe1ad7ae..2d7c435e8b4 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -2,6 +2,30 @@ max-time: 3600 cmd: atrt-mysql-test-run args: --force +max-time: 600 +cmd: atrt-testBackup +args: -n NFMaster T1 + +max-time: 600 +cmd: atrt-testBackup +args: -n NFMasterAsSlave T1 + +max-time: 600 +cmd: atrt-testBackup +args: -n NFSlave T1 + +max-time: 600 +cmd: atrt-testBackup +args: -n FailMaster T1 + +max-time: 600 +cmd: atrt-testBackup +args: -n FailMasterAsSlave T1 + +max-time: 600 +cmd: atrt-testBackup +args: -n FailSlave T1 + max-time: 600 cmd: atrt-testBackup args: -n BackupOne T1 T6 T3 I3 diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp index 5e22468692e..7c5d1405f6b 100644 --- a/ndb/test/src/NdbBackup.cpp +++ b/ndb/test/src/NdbBackup.cpp @@ -245,6 +245,10 @@ NdbBackup::NFSlave(NdbRestarter& _restarter){ int NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz, bool onMaster){ { + int nNodes = _restarter.getNumDbNodes(); + if(nNodes == 1) + return NDBT_OK; + int nodeId = _restarter.getMasterNodeId(); CHECK(_restarter.restartOneDbNode(nodeId, false, true, true) == 0, @@ -255,15 +259,11 @@ NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz, CHECK(_restarter.startNodes(&nodeId, 1) == 0, "failed to start node"); - - NdbSleep_SecSleep(10); } - + CHECK(_restarter.waitClusterStarted() == 0, "waitClusterStarted failed"); - - int nNodes = _restarter.getNumDbNodes(); - + myRandom48Init(NdbTick_CurrentMillisecond()); for(int i = 0; i Date: Fri, 22 Apr 2005 09:40:44 +0200 Subject: [PATCH 11/47] bug#9969 - ndb missleading error message --- ndb/src/ndbapi/ndberror.c | 6 +++--- ndb/test/src/NdbBackup.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 484e91f2977..98cce88e2a7 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -140,10 +140,10 @@ ErrorBundle ErrorCodes[] = { { 4008, UR, "Receive from NDB failed" }, { 4009, UR, "Cluster Failure" }, { 4012, UR, - "Time-out, most likely caused by simple read or cluster failure" }, + "Request ndbd time-out, maybe due to high load or communication problems"}, { 4024, UR, - "Time-out, most likely caused by simple read or cluster failure" }, - + "Time-out, most likely caused by simple read or cluster failure" }, + /** * TemporaryResourceError */ diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp index 7c5d1405f6b..28724323bd7 100644 --- a/ndb/test/src/NdbBackup.cpp +++ b/ndb/test/src/NdbBackup.cpp @@ -244,8 +244,8 @@ NdbBackup::NFSlave(NdbRestarter& _restarter){ int NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz, bool onMaster){ + int nNodes = _restarter.getNumDbNodes(); { - int nNodes = _restarter.getNumDbNodes(); if(nNodes == 1) return NDBT_OK; From 0bfc92467255010583aa4eee6166d69ea7cfff76 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Fri, 22 Apr 2005 11:04:26 +0200 Subject: [PATCH 12/47] bug#9724 - ndb restart if file already open occur print files... --- ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp b/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp index b944bb5485b..0fee687f1bc 100644 --- a/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp +++ b/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp @@ -82,8 +82,14 @@ inline bool OpenFiles::insert(AsyncFile* file, Uint16 id){ continue; if(strcmp(m_files[i].m_file->theFileName.c_str(), - file->theFileName.c_str()) == 0){ - ERROR_SET(fatal, AFS_ERROR_ALLREADY_OPEN,"","OpenFiles::insert()"); + file->theFileName.c_str()) == 0) + { + BaseString names; + names.assfmt("open: >%s< existing: >%s<", + file->theFileName.c_str(), + m_files[i].m_file->theFileName.c_str()); + ERROR_SET(fatal, AFS_ERROR_ALLREADY_OPEN, names.c_str(), + "OpenFiles::insert()"); } } From 70ed0ea4cb109262fe3ba18705f94f4f70fcf239 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Fri, 22 Apr 2005 20:49:05 +0200 Subject: [PATCH 13/47] Step 3 of the switch to support configuration with NPTL: Change "configure.in". The branches for Tru64 (ex: OSF/1) and Linux are separated, and for Linux 'getconf GNU_LIBPTHREAD_VERSION' is used to tell between Linuxthreads and NPTL. --- configure.in | 138 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 53 deletions(-) diff --git a/configure.in b/configure.in index f7a266eebec..dfffecdff08 100644 --- a/configure.in +++ b/configure.in @@ -411,12 +411,12 @@ if expr "$target_os" : "[[Ll]]inux.*" > /dev/null then MYSQLD_DEFAULT_SWITCHES="--skip-locking" TARGET_LINUX="true" - AC_MSG_RESULT("yes"); + AC_MSG_RESULT("yes") AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" TARGET_LINUX="false" - AC_MSG_RESULT("no"); + AC_MSG_RESULT("no") fi AC_SUBST(MYSQLD_DEFAULT_SWITCHES) AC_SUBST(TARGET_LINUX) @@ -1267,61 +1267,93 @@ esac # We have to check libc last because else it fails on Solaris 2.6 with_posix_threads="no" -# Hack for DEC-UNIX (OSF1) +# Search thread lib on Linux if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" then - # Look for LinuxThreads. - AC_MSG_CHECKING("LinuxThreads") - res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` - if test "$res" -gt 0 + AC_MSG_CHECKING("Linux threads") + if test "$TARGET_LINUX" = "true" then - AC_MSG_RESULT("Found") - AC_DEFINE([HAVE_LINUXTHREADS], [1], - [Whether we are using Xavier Leroy's LinuxThreads]) - # Linux 2.0 sanity check - AC_TRY_COMPILE([#include ], [int a = sched_get_priority_min(1);], , - AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual])) - # RedHat 5.0 does not work with dynamic linking of this. -static also - # gives a speed increase in linux so it does not hurt on other systems. - with_named_thread="-lpthread" - else - AC_MSG_RESULT("Not found") - # If this is a linux machine we should barf - if test "$TARGET_LINUX" = "true" - then - AC_MSG_ERROR([This is a linux system and Linuxthreads was not -found. On linux Linuxthreads should be used. Please install Linuxthreads -(or a new glibc) and try again. See the Installation chapter in the -Reference Manual for more information.]) - else - AC_MSG_CHECKING("DEC threads") - if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a - then - with_named_thread="-lpthread -lmach -lexc" - CFLAGS="$CFLAGS -D_REENTRANT" - CXXFLAGS="$CXXFLAGS -D_REENTRANT" - AC_DEFINE(HAVE_DEC_THREADS, [1], - [Whether we are using DEC threads]) - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") - AC_MSG_CHECKING("DEC 3.2 threads") - if test -f /usr/shlib/libpthreads.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a - then - with_named_thread="-lpthreads -lmach -lc_r" - AC_DEFINE(HAVE_DEC_THREADS, [1]) - AC_DEFINE([HAVE_DEC_3_2_THREADS], [1], - [Whether we are using OSF1 DEC threads on 3.2]) - with_osf32_threads="yes" - MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority" - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") + AC_MSG_RESULT("starting") + # use getconf to check glibc contents + AC_MSG_CHECKING("getconf GNU_LIBPTHREAD_VERSION") + case `getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` in + NPTL* ) + AC_MSG_RESULT("NPTL") + AC_DEFINE([HAVE_NPTL], [1], [NPTL threads implementation]) + with_named_thread="-lpthread" + ;; + LINUXTHREADS* ) + AC_MSG_RESULT("Linuxthreads") + AC_DEFINE([HAVE_LINUXTHREADS], [1], + [Whether we are using Xavier Leroy's LinuxThreads]) + with_named_thread="-lpthread" + ;; + * ) + AC_MSG_RESULT("unknown") + ;; + esac + if test "$with_named_thread" = "no" + then + # old method, check headers + # Look for LinuxThreads. + AC_MSG_CHECKING("LinuxThreads in header file comment") + res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` + if test "$res" -gt 0 + then + AC_MSG_RESULT("Found") + AC_DEFINE([HAVE_LINUXTHREADS], [1], + [Whether we are using Xavier Leroy's LinuxThreads]) + # Linux 2.0 sanity check + AC_TRY_COMPILE([#include ], [int a = sched_get_priority_min(1);], , + AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual])) + # RedHat 5.0 does not work with dynamic linking of this. -static also + # gives a speed increase in linux so it does not hurt on other systems. + with_named_thread="-lpthread" + else + AC_MSG_RESULT("Not found") + # If this is a linux machine we should barf + AC_MSG_ERROR([This is a Linux system without a working getconf, +and Linuxthreads was not found. Please install it (or a new glibc) and try again. +See the Installation chapter in the Reference Manual for more information.]) fi - fi - fi - fi -fi + else + AC_MSG_RESULT("no need to check headers") + fi + + AC_MSG_CHECKING("for pthread_create in -lpthread"); + ac_save_LIBS="$LIBS" + LIBS="$LIBS -lpthread" + AC_TRY_LINK( [#include ], + [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ], + AC_MSG_RESULT("yes"), + [ AC_MSG_RESULT("no") + AC_MSG_ERROR([ +This is a Linux system claiming to support threads, either Linuxthreads or NPTL, but linking a test program failed. +Please install one of these (or a new glibc) and try again. +See the Installation chapter in the Reference Manual for more information.]) ] + ) + LIBS="$ac_save_LIBS" + else + AC_MSG_RESULT("no") + fi # "$TARGET_LINUX" +fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no" + + +# Hack for DEC-UNIX (OSF1 -> Tru64) +if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" +then + AC_MSG_CHECKING("DEC threads post OSF/1 3.2") + if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a + then + with_named_thread="-lpthread -lmach -lexc" + CFLAGS="$CFLAGS -D_REENTRANT" + CXXFLAGS="$CXXFLAGS -D_REENTRANT" + AC_DEFINE(HAVE_DEC_THREADS, [1], [Whether we are using DEC threads]) + AC_MSG_RESULT("yes") + else + AC_MSG_RESULT("no") + fi # DEC threads +fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no" dnl This is needed because -lsocket has to come after the thread From d9d1c933b05b3d35ad9a45d052d97ffdba479f11 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Sun, 24 Apr 2005 20:34:42 +0200 Subject: [PATCH 14/47] bug#9924 - ndb backup - abort handling uninit variable --- ndb/src/kernel/blocks/backup/Backup.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 713991a4f58..d1bf4e55f95 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -2263,6 +2263,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) ptr.p->backupDataLen = req->backupDataLen; ptr.p->masterData.dropTrig.tableId = RNIL; ptr.p->masterData.alterTrig.tableId = RNIL; + ptr.p->masterData.errorCode = 0; ptr.p->noOfBytes = 0; ptr.p->noOfRecords = 0; ptr.p->noOfLogBytes = 0; From 763d835a3c073e2726c45b32b5b42d51a5d2fb68 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Mon, 25 Apr 2005 08:35:18 +0200 Subject: [PATCH 15/47] bug#9924 - ndb backup remove incorrect assertion --- ndb/src/kernel/blocks/backup/Backup.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index d1bf4e55f95..3ef73beb8d2 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -665,10 +665,6 @@ Backup::checkNodeFail(Signal* signal, NodeId newCoord, Uint32 theFailedNodes[NodeBitmask::Size]) { - ndbrequire( ptr.p->nodes.get(newCoord)); /* just to make sure newCoord - * is part of the backup - */ - NdbNodeBitmask mask; mask.assign(2, theFailedNodes); From 12e0d4f588ee6f1a05acddd7a48fd67d4e1de25e Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Mon, 25 Apr 2005 08:43:16 +0200 Subject: [PATCH 16/47] ndb - autotest add more tests to verify correctness of backups --- ndb/test/run-test/daily-basic-tests.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 2d7c435e8b4..e7753f758a1 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -6,26 +6,50 @@ max-time: 600 cmd: atrt-testBackup args: -n NFMaster T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n NFMasterAsSlave T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n NFSlave T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n FailMaster T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n FailMasterAsSlave T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n FailSlave T1 +max-time: 600 +cmd: testBasic +args: -n PkRead T1 + max-time: 600 cmd: atrt-testBackup args: -n BackupOne T1 T6 T3 I3 From a4a4c5cb69671329d863e5af04fe114734e731e5 Mon Sep 17 00:00:00 2001 From: "dlenev@brandersnatch.localdomain" <> Date: Mon, 25 Apr 2005 11:25:40 +0400 Subject: [PATCH 17/47] Fix for func_sapdb failures on 64-bit platforms (aka Bug #10040 "'func_sapdb' fails on 64bit build hosts") --- sql/item_timefunc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 6715930bc61..23cd9c7ced2 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -800,14 +800,14 @@ static bool calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign, We should check it before calc_time_diff call. */ if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value - days= l_time1->day - l_sign*l_time2->day; + days= (long)l_time1->day - l_sign * (long)l_time2->day; else { days= calc_daynr((uint) l_time1->year, (uint) l_time1->month, (uint) l_time1->day); if (l_time2->time_type == MYSQL_TIMESTAMP_TIME) - days-= l_sign*l_time2->day; + days-= l_sign * (long)l_time2->day; else days-= l_sign*calc_daynr((uint) l_time2->year, (uint) l_time2->month, From 3a9af0553b1ea1056ce0cfea531f46ca1f826b36 Mon Sep 17 00:00:00 2001 From: "mskold@mysql.com" <> Date: Mon, 25 Apr 2005 11:31:16 +0200 Subject: [PATCH 18/47] Post review fix of ndbcluster_drop_database --- sql/ha_ndbcluster.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 230ca2826b2..bb20cedec2e 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB + /* Copyright (C) 2000-2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4327,6 +4327,7 @@ int ndbcluster_drop_database(const char *path) uint i; char *tabname; List drop_list; + int ret= 0; ha_ndbcluster::set_dbname(path, (char *)&dbname); DBUG_PRINT("enter", ("db: %s", dbname)); @@ -4353,10 +4354,15 @@ int ndbcluster_drop_database(const char *path) ndb->setDatabaseName(dbname); List_iterator_fast it(drop_list); while ((tabname=it++)) - if (dict->dropTable(tabname)) - ERR_RETURN(dict->getNdbError()); - - DBUG_RETURN(0); + { + if (!dict->dropTable(tabname)) + { + const NdbError err= dict->getNdbError(); + if (err.code != 709) + ret= ndb_to_mysql_error(&err); + } + } + DBUG_RETURN(ret); } From 4649d5c30f078b6c0254f877c239964978ee409a Mon Sep 17 00:00:00 2001 From: "mskold@mysql.com" <> Date: Mon, 25 Apr 2005 11:34:47 +0200 Subject: [PATCH 19/47] Post review fix of ndbcluster_drop_database, print error --- sql/ha_ndbcluster.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index bb20cedec2e..2077fcb8f2d 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4359,7 +4359,10 @@ int ndbcluster_drop_database(const char *path) { const NdbError err= dict->getNdbError(); if (err.code != 709) + { + ERR_PRINT(err); ret= ndb_to_mysql_error(&err); + } } } DBUG_RETURN(ret); From 93498bdf5a6d13b4bf9e8a3d996df09b8f68799e Mon Sep 17 00:00:00 2001 From: "mskold@mysql.com" <> Date: Mon, 25 Apr 2005 11:54:00 +0200 Subject: [PATCH 20/47] Post review fix of ndbcluster_drop_database, typo --- sql/ha_ndbcluster.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 2077fcb8f2d..8c12cccf5ee 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4355,7 +4355,7 @@ int ndbcluster_drop_database(const char *path) List_iterator_fast it(drop_list); while ((tabname=it++)) { - if (!dict->dropTable(tabname)) + if (dict->dropTable(tabname)) { const NdbError err= dict->getNdbError(); if (err.code != 709) From 280bef18457bef5a489020db7c836ad5399378f2 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Mon, 25 Apr 2005 11:59:00 +0200 Subject: [PATCH 21/47] bug#9749 - ndb lock upgrade post review fix. don't init hash value on restart operations make sure that lock mode is correct in entire que. --- ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 13 ++++++------- ndb/test/ndbapi/testOperations.cpp | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index d566639489c..44c891fc220 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -5899,33 +5899,32 @@ Dbacc::check_lock_upgrade(Signal* signal, // Find end of parallell que tmp = lock_owner; + Uint32 lockMode = next.p->lockMode > lock_owner.p->lockMode ? + next.p->lockMode : lock_owner.p->lockMode; while(tmp.p->nextParallelQue != RNIL) { jam(); tmp.i = tmp.p->nextParallelQue; + tmp.p->lockMode = lockMode; ptrCheckGuard(tmp, coprecsize, operationrec); } + tmp.p->lockMode = lockMode; next.p->prevParallelQue = tmp.i; tmp.p->nextParallelQue = next.i; OperationrecPtr save = operationRecPtr; - Uint32 lockMode = lock_owner.p->lockMode; - Uint32 TelementIsDisappeared = 0; // lock upgrade = all reads - Uint32 ThashValue = lock_owner.p->hashValue; Uint32 localdata[2]; localdata[0] = lock_owner.p->localdata[0]; localdata[1] = lock_owner.p->localdata[1]; do { - next.p->elementIsDisappeared = TelementIsDisappeared; - next.p->hashValue = ThashValue; next.p->localdata[0] = localdata[0]; next.p->localdata[1] = localdata[1]; + next.p->lockMode = lockMode; operationRecPtr = next; - next.p->lockMode = lockMode; - TelementIsDisappeared = executeNextOperation(signal); + executeNextOperation(signal); if (next.p->nextParallelQue != RNIL) { jam(); diff --git a/ndb/test/ndbapi/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp index 773511a0475..726f35b01fb 100644 --- a/ndb/test/ndbapi/testOperations.cpp +++ b/ndb/test/ndbapi/testOperations.cpp @@ -635,7 +635,14 @@ runLockUpgrade2(NDBT_Context* ctx, NDBT_Step* step){ ndbout_c("wait 3 - done"); NdbSleep_MilliSleep(200); - CHECK(hugoOps.execute_Commit(pNdb) == 0); + if(ctx->getProperty("LU_COMMIT", (Uint32)0) == 0) + { + CHECK(hugoOps.execute_Commit(pNdb) == 0); + } + else + { + CHECK(hugoOps.execute_Rollback(pNdb) == 0); + } } while(0); return result; @@ -650,7 +657,7 @@ main(int argc, const char** argv){ NDBT_TestSuite ts("testOperations"); - for(Uint32 i = 0; i <6; i++) + for(Uint32 i = 0; i < 12; i++) { BaseString name("bug_9749"); name.appfmt("_%d", i); @@ -658,8 +665,9 @@ main(int argc, const char** argv){ name.c_str(), ""); pt->setProperty("LOCK_UPGRADE", 1 + (i & 1)); - pt->setProperty("LU_OP", 1 + (i >> 1)); - + pt->setProperty("LU_OP", 1 + ((i >> 1) % 3)); + pt->setProperty("LU_COMMIT", i / 6); + pt->addInitializer(new NDBT_Initializer(pt, "runClearTable", runClearTable)); From cd10a69be2afb0f2fcea48446160c0ba2c645b9d Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 25 Apr 2005 12:58:03 +0200 Subject: [PATCH 22/47] - bumped up version number in configure.in to 5.0.6 now that engineering branched off for the 5.0.5 builds - tagged ChangeSet 1.1882 as the "clone-5.0.5-build" branchoff point --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index f4ced66a06d..882267c260e 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.50)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.5-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.6-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 83978acd5a8f5311fcbd04780fabeae1a6a2015d Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 25 Apr 2005 13:18:44 +0200 Subject: [PATCH 23/47] - update NDB_VERSION_BUILD, too --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 882267c260e..a160f84a165 100644 --- a/configure.in +++ b/configure.in @@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=4 +NDB_VERSION_BUILD=6 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From 83c289665fa0e94bb5f6e4e29af3abacc3bf17f7 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 25 Apr 2005 13:28:07 +0200 Subject: [PATCH 24/47] - fixed NDB_VERSION_BUILD in configure.in to have the correct number (4->5) --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index f4ced66a06d..d3e0bf6cefe 100644 --- a/configure.in +++ b/configure.in @@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=4 +NDB_VERSION_BUILD=5 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From a22ec942ac0c594ebfa9d650333d05afad6f194a Mon Sep 17 00:00:00 2001 From: "reggie@mdk10.(none)" <> Date: Mon, 25 Apr 2005 16:53:47 -0500 Subject: [PATCH 25/47] regerror.c: Changed function signature to fix compile errors with Whidbey --- regex/regerror.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/regex/regerror.c b/regex/regerror.c index 0a7b7c8da2c..9caa5b95a4c 100644 --- a/regex/regerror.c +++ b/regex/regerror.c @@ -56,11 +56,7 @@ static struct rerr { */ /* ARGSUSED */ size_t -regerror(errcode, preg, errbuf, errbuf_size) -int errcode; -const regex_t *preg; -char *errbuf; -size_t errbuf_size; +regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { register struct rerr *r; register size_t len; From a27e830385b8b19e26737218ba291b0730c84dde Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 26 Apr 2005 01:56:10 +0400 Subject: [PATCH 26/47] BUG#10037: A proper fix: Add 0.01 to cost of 'range' scans, don't add 0.01 to cost of the 'index' scan. --- sql/opt_range.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ac25f15d460..95fe003770b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2257,8 +2257,7 @@ inline double get_index_only_read_time(const PARAM* param, ha_rows records, param->table->file->ref_length) + 1); read_time=((double) (records+keys_per_block-1)/ (double) keys_per_block); - /* Add 0.01 to avoid cost races between 'range' and 'index' */ - return read_time + 0.01; + return read_time; } @@ -3150,10 +3149,16 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, (param->table->file->index_flags(keynr, param->max_key_part,1) & HA_KEYREAD_ONLY) && !(pk_is_clustered && keynr == param->table->s->primary_key)) - /* We can resolve this by only reading through this key. */ + { + /* + We can resolve this by only reading through this key. + 0.01 is added to avoid races between range and 'index' scan. + */ found_read_time= get_index_only_read_time(param,found_records,keynr) + - cpu_cost; + cpu_cost + 0.01; + } else + { /* cost(read_through_index) = cost(disk_io) + cost(row_in_range_checks) The row_in_range check is in QUICK_RANGE_SELECT::cmp_next function. @@ -3161,8 +3166,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, found_read_time= param->table->file->read_time(keynr, param->range_count, found_records) + - cpu_cost; - + cpu_cost + 0.01; + } DBUG_PRINT("info",("key %s: found_read_time: %g (cur. read_time: %g)", param->table->key_info[keynr].name, found_read_time, read_time)); From 93ff028f9d9331d1fa536b77b006bfe7f8fb70df Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Mon, 25 Apr 2005 18:02:03 -0700 Subject: [PATCH 27/47] Fix compile issues in Intel C/C++ compiler (Bug #9063) --- acinclude.m4 | 39 ++++++++++++++++++++++++++++++++++----- configure.in | 2 ++ sql/mysqld.cc | 2 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 74426bc2061..904493a2e09 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -97,10 +97,10 @@ undefine([AC_CV_NAME])dnl AC_DEFUN([MYSQL_TYPE_ACCEPT], [ac_save_CXXFLAGS="$CXXFLAGS" AC_CACHE_CHECK([base type of last arg to accept], mysql_cv_btype_last_arg_accept, -AC_LANG_SAVE -AC_LANG_CPLUSPLUS +AC_LANG_PUSH(C++) if test "$ac_cv_prog_gxx" = "yes" then + # Add -Werror, remove -fbranch-probabilities (Bug #268) CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'` fi mysql_cv_btype_last_arg_accept=none @@ -127,7 +127,7 @@ fi if test "$mysql_cv_btype_last_arg_accept" = "none"; then mysql_cv_btype_last_arg_accept=int fi) -AC_LANG_RESTORE +AC_LANG_POP(C++) AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept], [The base type of the last arg to accept]) CXXFLAGS="$ac_save_CXXFLAGS" @@ -153,6 +153,35 @@ then fi ]) +#---START: Figure out whether to use 'struct rlimit' or 'struct rlimit64' +AC_DEFUN([MYSQL_TYPE_STRUCT_RLIMIT], +[ac_save_CXXFLAGS="$CXXFLAGS" +AC_CACHE_CHECK([struct type to use with setrlimit], mysql_cv_btype_struct_rlimit, +AC_LANG_PUSH(C++) +if test "$ac_cv_prog_gxx" = "yes" +then + # Add -Werror, remove -fbranch-probabilities (Bug #268) + CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'` +fi +mysql_cv_btype_struct_rlimit=none +[AC_TRY_COMPILE([#if defined(inline) +#undef inline +#endif +#include +#include +], +[struct rlimit64 rl; setrlimit(RLIMIT_CORE, &rl);], +mysql_cv_btype_struct_rlimit="struct rlimit64")] +if test "$mysql_cv_btype_struct_rlimit" = "none"; then +mysql_cv_btype_struct_rlimit="struct rlimit" +fi) +AC_LANG_POP(C++) +AC_DEFINE_UNQUOTED([STRUCT_RLIMIT], [$mysql_cv_btype_struct_rlimit], + [The struct rlimit type to use with setrlimit]) +CXXFLAGS="$ac_save_CXXFLAGS" +]) +#---END: + AC_DEFUN([MYSQL_TIMESPEC_TS], [AC_CACHE_CHECK([if struct timespec has a ts_sec member], mysql_cv_timespec_ts, [AC_TRY_COMPILE([#include @@ -1940,8 +1969,8 @@ m4_define([_AC_PROG_CXX_EXIT_DECLARATION], 'void exit (int);' \ '#include ' do - _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include -$ac_declaration], + _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration +@%:@include ], [exit (42);])], [], [continue]) diff --git a/configure.in b/configure.in index d191463d0f9..8191d46c0e6 100644 --- a/configure.in +++ b/configure.in @@ -1795,6 +1795,8 @@ AC_C_BIGENDIAN MYSQL_TYPE_ACCEPT #---END: +# Figure out what type of struct rlimit to use with setrlimit +MYSQL_TYPE_STRUCT_RLIMIT # Find where the stack goes MYSQL_STACK_DIRECTION # We want to skip alloca on irix unconditionally. It may work on some version.. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 056c2a7ad7f..43bed35621b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2000,7 +2000,7 @@ static void init_signals(void) if (test_flags & TEST_CORE_ON_SIGNAL) { /* Change limits so that we will get a core file */ - struct rlimit rl; + STRUCT_RLIMIT rl; rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings) sql_print_warning("setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals"); From 1523119091522b364692dcb65e181d7e193d65ee Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 26 Apr 2005 12:16:12 +0200 Subject: [PATCH 28/47] Post-merge fix of the fixes for NPTL configuration (bug#2173, bug#5871, and bug#9497). --- config/ac-macros/openssl.m4 | 2 +- include/my_global.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/ac-macros/openssl.m4 b/config/ac-macros/openssl.m4 index 6541a492247..aa46dd45360 100644 --- a/config/ac-macros/openssl.m4 +++ b/config/ac-macros/openssl.m4 @@ -44,7 +44,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then echo "Could not find an installation of OpenSSL" if test -n "$OPENSSL_LIB" ; then - if test "$IS_LINUX" = "true"; then + if test "$TARGET_LINUX" = "true"; then echo "Looks like you've forgotten to install OpenSSL development RPM" fi fi diff --git a/include/my_global.h b/include/my_global.h index 6cd1277d358..74846fe1762 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -107,6 +107,7 @@ #undef THREAD #undef HAVE_mit_thread #undef HAVE_LINUXTHREADS +#undef HAVE_NPTL #undef HAVE_UNIXWARE7_THREADS #endif From 7882cd32bcfef6681e2c6fcd6cf7fd970e62e837 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Tue, 26 Apr 2005 15:43:20 +0500 Subject: [PATCH 29/47] A fix (bug #9756: mysql client failing on dumps containing certain \ sequences). --- mysys/charset.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mysys/charset.c b/mysys/charset.c index a4a8205a3f9..534a6aa998e 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -581,15 +581,15 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { char escape=0; #ifdef USE_MB - int l; - if (use_mb_flag && (l= my_ismbchar(charset_info, from, end))) + int tmp_length; + if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) { - if (to + l >= to_end) + if (to + tmp_length > to_end) { overflow=1; break; } - while (l--) + while (tmp_length--) *to++= *from++; from--; continue; @@ -605,7 +605,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, multi-byte character into a valid one. For example, 0xbf27 is not a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \) */ - if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1) + if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1) escape= *from; else #endif @@ -634,7 +634,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, } if (escape) { - if (to + 2 >= to_end) + if (to + 2 > to_end) { overflow=1; break; @@ -644,7 +644,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, } else { - if (to + 1 >= to_end) + if (to + 1 > to_end) { overflow=1; break; From 12d14eb96c9c667b054f13996bdc10e5e26eeca0 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Tue, 26 Apr 2005 15:48:16 +0500 Subject: [PATCH 30/47] Test case (bug #9756: mysql client failing on dumps containing certain \ sequences). --- mysql-test/r/mysqldump.result | 32 ++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 8 ++++++++ 2 files changed, 40 insertions(+) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 130bda3e5bb..fdbdd26b00c 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -599,3 +599,35 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +CREATE TABLE t1 (a char(10)); +INSERT INTO t1 VALUES ('\''); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('\''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index ca883f5c4d2..949c62ef288 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -196,3 +196,11 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; +# +# Bug #9756 +# + +CREATE TABLE t1 (a char(10)); +INSERT INTO t1 VALUES ('\''); +--exec $MYSQL_DUMP --skip-comments test t1 +DROP TABLE t1; From 0ca934de63a8737a2c90315765ef1830afab950c Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 26 Apr 2005 14:02:16 +0300 Subject: [PATCH 31/47] Improved client internal help. Doc fix for Bug#9870. --- client/mysql.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 8d5117a29e0..4eed4349b45 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include #endif -const char *VER= "14.9"; +const char *VER= "14.10"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -235,7 +235,7 @@ static COMMANDS commands[] = { { "connect",'r', com_connect,1, "Reconnect to the server. Optional arguments are db and host." }, { "delimiter", 'd', com_delimiter, 1, - "Set query delimiter. " }, + "Set statement delimiter. NOTE: Takes the rest of the line as new delimiter." }, #ifdef USE_POPEN { "edit", 'e', com_edit, 0, "Edit command with $EDITOR."}, #endif From 74fdb2663cb97bac5bb60f0aa2431bd9f951b787 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 26 Apr 2005 13:15:20 +0200 Subject: [PATCH 32/47] Final fix for NPTL configuration (bug#2173, bug#5871, and bug#9497). --- include/my_global.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/my_global.h b/include/my_global.h index a027bf9d2bb..745179e8a06 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -107,6 +107,7 @@ #undef THREAD #undef HAVE_mit_thread #undef HAVE_LINUXTHREADS +#undef HAVE_NPTL #undef HAVE_UNIXWARE7_THREADS #endif From 7810721f401c28193af8cecb22dc9b047681fb23 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 26 Apr 2005 14:28:22 +0300 Subject: [PATCH 33/47] Fixed Bug#9835: mysqld_multi --help won't output help if there are parameter problems. --- scripts/mysqld_multi.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index ee873a86c8d..e4895ae4bef 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -4,7 +4,7 @@ use Getopt::Long; use POSIX qw(strftime); $|=1; -$VER="2.12"; +$VER="2.13"; $opt_config_file = undef(); $opt_example = 0; @@ -37,13 +37,13 @@ main(); sub main { - my ($flag_exit); + my $flag_exit= 0; if (!defined(my_which(my_print_defaults))) { # We can't throw out yet, since --version, --help, or --example may # have been given - print "WARNING! my_print_defaults command not found!\n"; + print "WARNING: my_print_defaults command not found.\n"; print "Please make sure you have this command available and\n"; print "in your path. The command is available from the latest\n"; print "MySQL distribution.\n"; @@ -76,10 +76,14 @@ sub main chop @defops; splice @ARGV, 0, 0, @defops; } - GetOptions("help","example","version","mysqld=s","mysqladmin=s", - "config-file=s","user=s","password=s","log=s","no-log","tcp-ip", - "silent","verbose") - || die "Wrong option! See $my_progname --help for detailed information!\n"; + if (!GetOptions("help","example","version","mysqld=s","mysqladmin=s", + "config-file=s","user=s","password=s","log=s","no-log", + "tcp-ip", "silent","verbose")) + { + $flag_exit= 1; + } + + usage() if ($opt_help); if ($opt_verbose && $opt_silent) { @@ -95,15 +99,14 @@ sub main exit(0); } example() if ($opt_example); - usage() if ($opt_help); if ($flag_exit) { - print "Error with an option, see $my_progname --help for more info!\n"; + print "Error with an option, see $my_progname --help for more info.\n"; exit(1); } if (!defined(my_which(my_print_defaults))) { - print "ABORT: Can't find command 'my_print_defaults'!\n"; + print "ABORT: Can't find command 'my_print_defaults'.\n"; print "This command is available from the latest MySQL\n"; print "distribution. Please make sure you have the command\n"; print "in your PATH.\n"; From d4d0f9c1269cbac0c7accca7d27eb97138eb3a49 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 26 Apr 2005 16:16:38 +0300 Subject: [PATCH 34/47] Fixed Bug#6221, "mysqld_multi doesn't read the init_connect option in my.cnf correctly" --- scripts/mysqld_multi.sh | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index e4895ae4bef..8c363836a25 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -4,7 +4,7 @@ use Getopt::Long; use POSIX qw(strftime); $|=1; -$VER="2.13"; +$VER="2.14"; $opt_config_file = undef(); $opt_example = 0; @@ -159,6 +159,31 @@ sub main } } +#### +#### Quote option argument. Add double quotes around the argument +#### and escape the following: $, \, " +#### This function is needed, because my_print_defaults drops possible +#### quotes, single or double, from in front of an argument and from +#### the end. +#### + +sub quote_opt_arg +{ + my ($option)= @_; + + if ($option =~ m/(\-\-[a-zA-Z0-9\_\-]+)=(.*)/) + { + $option= $1; + $arg= $2; + $arg=~ s/\\/\\\\/g; # Escape escape character first to avoid doubling. + $arg=~ s/\$/\\\$/g; + $arg=~ s/\"/\\\"/g; + $arg= "\"" . $arg . "\""; + $option= $option . "=" . $arg; + } + return $option; +} + #### #### Init log file. Check for appropriate place for log file, in the following #### order my_print_defaults mysqld datadir, @datadir@, /var/log, /tmp @@ -293,6 +318,7 @@ sub start_mysqlds() else { $options[$j]=~ s/;/\\;/g; + $options[$j]= quote_opt_arg($options[$j]); $tmp.= " $options[$j]"; } } From a95571875c3113c052e14266d7ae33054ee28777 Mon Sep 17 00:00:00 2001 From: "gbichot@quadita2.mysql.com" <> Date: Tue, 26 Apr 2005 15:52:04 +0200 Subject: [PATCH 35/47] checking that statements get into binlog even when they were affecting no rows of the blackhold engine (for this engine to be a binlog propagator). NOTE: blackhole.test currently hangs in 5.0 BUG#10175 so I'll merge without running this test; the person who fixes the hang will correct the merged blackhole.result or ask me to). --- mysql-test/r/blackhole.result | 41 ++++++++++++++++++++++++++++++++++- mysql-test/t/blackhole.test | 30 ++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result index 20018dcb089..4b779094376 100644 --- a/mysql-test/r/blackhole.result +++ b/mysql-test/r/blackhole.result @@ -83,4 +83,43 @@ Full-text indexes are called collections Only MyISAM tables support collections select * from t1 where MATCH(a,b) AGAINST ("only"); a b -drop table if exists t1,t2; +reset master; +drop table t1,t2; +create table t1 (a int) engine=blackhole; +delete from t1 where a=10; +update t1 set a=11 where a=15; +insert into t1 values(1); +insert ignore into t1 values(1); +replace into t1 values(100); +create table t2 (a varchar(200)) engine=blackhole; +load data infile '../../std_data/words.dat' into table t2; +alter table t1 add b int; +alter table t1 drop b; +create table t3 like t1; +insert into t1 select * from t3; +replace into t1 select * from t3; +select * from t1; +a +select * from t2; +a +select * from t3; +a +show binlog events; +Log_name Pos Event_type Server_id Orig_log_pos Info +master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3 +master-bin.000001 # Query 1 # use `test`; drop table t1,t2 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) engine=blackhole +master-bin.000001 # Query 1 # use `test`; delete from t1 where a=10 +master-bin.000001 # Query 1 # use `test`; update t1 set a=11 where a=15 +master-bin.000001 # Query 1 # use `test`; insert into t1 values(1) +master-bin.000001 # Query 1 # use `test`; insert ignore into t1 values(1) +master-bin.000001 # Query 1 # use `test`; replace into t1 values(100) +master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole +master-bin.000001 # Create_file 1 # db=test;table=t2;file_id=1;block_len=581 +master-bin.000001 # Exec_load 1 # ;file_id=1 +master-bin.000001 # Query 1 # use `test`; alter table t1 add b int +master-bin.000001 # Query 1 # use `test`; alter table t1 drop b +master-bin.000001 # Query 1 # use `test`; create table t3 like t1 +master-bin.000001 # Query 1 # use `test`; insert into t1 select * from t3 +master-bin.000001 # Query 1 # use `test`; replace into t1 select * from t3 +drop table t1,t2,t3; diff --git a/mysql-test/t/blackhole.test b/mysql-test/t/blackhole.test index 052574d6921..d1fcfc971a9 100644 --- a/mysql-test/t/blackhole.test +++ b/mysql-test/t/blackhole.test @@ -96,4 +96,32 @@ select * from t1 where MATCH(a,b) AGAINST ("indexes"); select * from t1 where MATCH(a,b) AGAINST ("indexes collections"); select * from t1 where MATCH(a,b) AGAINST ("only"); -drop table if exists t1,t2; +# Test that every DML (except SELECT) and DDL gets into binlog +# so that blackhole can be used as "binlog propagator" + +reset master; +drop table t1,t2; +create table t1 (a int) engine=blackhole; +delete from t1 where a=10; +update t1 set a=11 where a=15; +insert into t1 values(1); +insert ignore into t1 values(1); +replace into t1 values(100); +create table t2 (a varchar(200)) engine=blackhole; +load data infile '../../std_data/words.dat' into table t2; +alter table t1 add b int; +alter table t1 drop b; +create table t3 like t1; +insert into t1 select * from t3; +replace into t1 select * from t3; +# Just to verify +select * from t1; +select * from t2; +select * from t3; + +let $VERSION=`select version()`; +--replace_result $VERSION VERSION +--replace_column 2 # 5 # +show binlog events; + +drop table t1,t2,t3; From c98b90bbfb168f5d5653380e54cd19eeba3b9fff Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 26 Apr 2005 17:46:43 +0300 Subject: [PATCH 36/47] Fixed Bug#9834, "mysqld_multi --config-file parameter requires absolute path". --- scripts/mysqld_multi.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 8c363836a25..19434c3dc27 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -66,6 +66,11 @@ sub main else { $opt_config_file= $1; + if (!($opt_config_file =~ m/\//)) + { + # No path. Use current working directory + $opt_config_file= "./" . $opt_config_file; + } } } } @@ -82,7 +87,11 @@ sub main { $flag_exit= 1; } - + if (!($opt_config_file =~ m/\//)) + { + # No path. Use current working directory + $opt_config_file= "./" . $opt_config_file; + } usage() if ($opt_help); if ($opt_verbose && $opt_silent) From db2b729c737cb5de3b56d7bc1870f0778ef71f2c Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Tue, 26 Apr 2005 19:46:52 +0500 Subject: [PATCH 37/47] A fix (bug #10176: problem with varchar keys). --- myisam/mi_key.c | 3 +++ mysql-test/include/varchar.inc | 10 ++++++++++ mysql-test/r/bdb.result | 9 +++++++++ mysql-test/r/innodb.result | 9 +++++++++ mysql-test/r/myisam.result | 9 +++++++++ 5 files changed, 40 insertions(+) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index ab5ddd3a378..d7d10e116aa 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -242,7 +242,10 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, { k_length-=length; if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART)) + { k_length-=2; /* Skip length */ + old+= 2; + } continue; /* Found NULL */ } } diff --git a/mysql-test/include/varchar.inc b/mysql-test/include/varchar.inc index 3ec9d00d05d..13b4315f2b8 100644 --- a/mysql-test/include/varchar.inc +++ b/mysql-test/include/varchar.inc @@ -226,3 +226,13 @@ create table t1 (v varchar(65530), key(v(10))); insert into t1 values(repeat('a',65530)); select length(v) from t1 where v=repeat('a',65530); drop table t1; + +# +# Bug #9489: problem with hash indexes +# + +create table t1(a int, b varchar(12), key ba(b, a)); +insert into t1 values (1, 'A'), (20, NULL); +explain select * from t1 where a=20 and b is null; +select * from t1 where a=20 and b is null; +drop table t1; diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index d743bc03675..876da3cb964 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1858,6 +1858,15 @@ select length(v) from t1 where v=repeat('a',65530); length(v) 65530 drop table t1; +create table t1(a int, b varchar(12), key ba(b, a)); +insert into t1 values (1, 'A'), (20, NULL); +explain select * from t1 where a=20 and b is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref ba ba 20 const,const 1 Using where +select * from t1 where a=20 and b is null; +a b +20 NULL +drop table t1; create table t1 (v varchar(65530), key(v)); Warnings: Warning 1071 Specified key was too long; max key length is 255 bytes diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index ccd8601ace0..d6cfefff9e6 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2359,6 +2359,15 @@ select length(v) from t1 where v=repeat('a',65530); length(v) 65530 drop table t1; +create table t1(a int, b varchar(12), key ba(b, a)); +insert into t1 values (1, 'A'), (20, NULL); +explain select * from t1 where a=20 and b is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref ba ba 20 const,const 1 Using where; Using index +select * from t1 where a=20 and b is null; +a b +20 NULL +drop table t1; create table t1 (v varchar(65530), key(v)); ERROR HY000: Can't create table './test/t1' (errno: 139) create table t1 (v varchar(65536)); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 539df03e6f9..1a8ace98d05 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1157,6 +1157,15 @@ select length(v) from t1 where v=repeat('a',65530); length(v) 65530 drop table t1; +create table t1(a int, b varchar(12), key ba(b, a)); +insert into t1 values (1, 'A'), (20, NULL); +explain select * from t1 where a=20 and b is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref ba ba 20 const,const 1 Using where; Using index +select * from t1 where a=20 and b is null; +a b +20 NULL +drop table t1; create table t1 (v varchar(65530), key(v)); Warnings: Warning 1071 Specified key was too long; max key length is 1000 bytes From 005c447183651411ead446e463909118f7020298 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 26 Apr 2005 17:57:14 +0300 Subject: [PATCH 38/47] Added a check for config-file. --- scripts/mysqld_multi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 19434c3dc27..642772bca44 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -87,7 +87,7 @@ sub main { $flag_exit= 1; } - if (!($opt_config_file =~ m/\//)) + if (defined($opt_config_file) && !($opt_config_file =~ m/\//)) { # No path. Use current working directory $opt_config_file= "./" . $opt_config_file; From a296ccfd286286f099ea75ab5859864765a05746 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Tue, 26 Apr 2005 08:20:00 -0700 Subject: [PATCH 39/47] Fix typo in include file name (Bug #9063) --- acinclude.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acinclude.m4 b/acinclude.m4 index 904493a2e09..61b37294377 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -168,7 +168,7 @@ mysql_cv_btype_struct_rlimit=none #undef inline #endif #include -#include +#include ], [struct rlimit64 rl; setrlimit(RLIMIT_CORE, &rl);], mysql_cv_btype_struct_rlimit="struct rlimit64")] From fcc04b2ffd51ab4fb4799c99054499e61eb42136 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Tue, 26 Apr 2005 08:23:42 -0700 Subject: [PATCH 40/47] Merge changes to acinclude.m4 that are now in config/ac-macros/misc.m4 --- config/ac-macros/misc.m4 | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index 186a069ac61..201702e5379 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -34,10 +34,10 @@ undefine([AC_CV_NAME])dnl AC_DEFUN([MYSQL_TYPE_ACCEPT], [ac_save_CXXFLAGS="$CXXFLAGS" AC_CACHE_CHECK([base type of last arg to accept], mysql_cv_btype_last_arg_accept, -AC_LANG_SAVE -AC_LANG_CPLUSPLUS +AC_LANG_PUSH(C++) if test "$ac_cv_prog_gxx" = "yes" then + # Add -Werror, remove -fbranch-probabilities (Bug #268) CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'` fi mysql_cv_btype_last_arg_accept=none @@ -64,7 +64,7 @@ fi if test "$mysql_cv_btype_last_arg_accept" = "none"; then mysql_cv_btype_last_arg_accept=int fi) -AC_LANG_RESTORE +AC_LANG_POP(C++) AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept], [The base type of the last arg to accept]) CXXFLAGS="$ac_save_CXXFLAGS" @@ -90,6 +90,35 @@ then fi ]) +#---START: Figure out whether to use 'struct rlimit' or 'struct rlimit64' +AC_DEFUN([MYSQL_TYPE_STRUCT_RLIMIT], +[ac_save_CXXFLAGS="$CXXFLAGS" +AC_CACHE_CHECK([struct type to use with setrlimit], mysql_cv_btype_struct_rlimit, +AC_LANG_PUSH(C++) +if test "$ac_cv_prog_gxx" = "yes" +then + # Add -Werror, remove -fbranch-probabilities (Bug #268) + CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'` +fi +mysql_cv_btype_struct_rlimit=none +[AC_TRY_COMPILE([#if defined(inline) +#undef inline +#endif +#include +#include +], +[struct rlimit64 rl; setrlimit(RLIMIT_CORE, &rl);], +mysql_cv_btype_struct_rlimit="struct rlimit64")] +if test "$mysql_cv_btype_struct_rlimit" = "none"; then +mysql_cv_btype_struct_rlimit="struct rlimit" +fi) +AC_LANG_POP(C++) +AC_DEFINE_UNQUOTED([STRUCT_RLIMIT], [$mysql_cv_btype_struct_rlimit], + [The struct rlimit type to use with setrlimit]) +CXXFLAGS="$ac_save_CXXFLAGS" +]) +#---END: + AC_DEFUN([MYSQL_TIMESPEC_TS], [AC_CACHE_CHECK([if struct timespec has a ts_sec member], mysql_cv_timespec_ts, [AC_TRY_COMPILE([#include From bea92e16463d9ada60a975298268fa2c13c4e53f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 02:57:19 +0300 Subject: [PATCH 41/47] dict0dict.c, dict0dict.h, fil0fil.c: Fix a problem in crash recovery of .ibd files on Windows if the user used lower_case_table_names=0 or 2; the directory scan in crash recovery forgot to put all paths to lower case, so that the tablespace name would be consistent with the internal data dictionary of InnoDB; remember that InnoDB puts internally all database names and table names to lower case on Windows, regardless of the value of lower_case_table_names --- innobase/dict/dict0dict.c | 12 +++++++++++- innobase/fil/fil0fil.c | 9 +++++++++ innobase/include/dict0dict.h | 7 +++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index bbc47fe9c2b..b0327f77fd3 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -197,7 +197,17 @@ FILE* dict_foreign_err_file = NULL; mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign and unique error buffers */ - +/********************************************************************** +Makes all characters in a NUL-terminated UTF-8 string lower case. */ + +void +dict_casedn_str( +/*============*/ + char* a) /* in/out: string to put in lower case */ +{ + innobase_casedn_str(a); +} + /************************************************************************ Checks if the database name in two table names is the same. */ diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 773bd709fb7..9d5def718a6 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -25,6 +25,7 @@ Created 10/25/1995 Heikki Tuuri #include "srv0start.h" #include "mtr0mtr.h" #include "mtr0log.h" +#include "dict0dict.h" /* @@ -2732,7 +2733,15 @@ fil_load_single_table_tablespace( sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname, filename); srv_normalize_path_for_win(filepath); +#ifdef __WIN__ + /* If lower_case_table_names is 0 or 2, then MySQL allows database + directory names with upper case letters. On Windows, all table and + database names in InnoDB are internally always in lower case. Put the + file path to lower case, so that we are consistent with InnoDB's + internal data dictionary. */ + dict_casedn_str(filepath); +#endif file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success); if (!success) { diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 745a776bda1..3333385ec56 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -26,6 +26,13 @@ Created 1/8/1996 Heikki Tuuri #include "ut0byte.h" #include "trx0types.h" +/********************************************************************** +Makes all characters in a NUL-terminated UTF-8 string lower case. */ + +void +dict_casedn_str( +/*============*/ + char* a); /* in/out: string to put in lower case */ /************************************************************************ Get the database name length in a table name. */ From 36c1766f5db7ba6d22dd97b45997eaf37e19f326 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 03:18:54 +0300 Subject: [PATCH 42/47] sql_repl.cc: Remove printf's from semi-sync code in sql_repl.cc --- sql/sql_repl.cc | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 72470c487a3..0dcfd985f88 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -385,8 +385,6 @@ impossible position"; goto err; } - printf("Binlog file name %s\n", log_file_name); - if (thd->variables.sync_replication) ha_repl_report_sent_binlog(thd, log_file_name, pos); @@ -537,9 +535,6 @@ impossible position"; goto err; } - printf("Dump loop: %s: Current log position %lu\n", log_file_name, - (ulong)my_b_tell(&log)); - if (thd->variables.sync_replication) ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log)); @@ -656,9 +651,6 @@ impossible position"; goto err; } - printf("Second loop: %s: Current log position %lu\n", log_file_name, - (ulong)my_b_tell(&log)); - if (thd->variables.sync_replication) ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log)); @@ -730,15 +722,12 @@ impossible position"; if (thd->variables.sync_replication) ha_repl_report_sent_binlog(thd, log_file_name, 0); - printf("Binlog file name of a new binlog %s\n", log_file_name); - packet->length(0); packet->append('\0'); } } end: - printf("Ending replication\n"); if (thd->variables.sync_replication) ha_repl_report_replication_stop(thd); @@ -756,8 +745,6 @@ err: if (thd->variables.sync_replication) ha_repl_report_replication_stop(thd); - printf("Ending replication in error %s\n", errmsg); - thd->proc_info = "Waiting to finalize termination"; end_io_cache(&log); /* From e93f8ec420cfe6145bdfb32666bfe4c903ea20f6 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 13:19:40 +0300 Subject: [PATCH 43/47] ha_innodb.cc: Fix linking and compilation errors --- sql/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e68a85bdac9..3aed42f9c38 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1619,7 +1619,7 @@ innobase_report_binlog_offset_and_commit( if (trx->repl_wait_binlog_name == NULL) { trx->repl_wait_binlog_name = - (char*)mem_alloc(FN_REFLEN + 100); + (char*)mem_alloc_noninline(FN_REFLEN + 100); } ut_a(strlen(log_file_name) <= FN_REFLEN + 100); From ab0dbb1fc6fc5a87c5a6b88d53a7ffef6ba618ea Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 13:36:58 +0300 Subject: [PATCH 44/47] ha_innodb.cc, mysqld.cc: Fix compilation error if HAVE_REPLICATION is not defined --- sql/ha_innodb.cc | 22 ++++++++++------------ sql/mysqld.cc | 2 ++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3aed42f9c38..7d77ae809b1 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1611,6 +1611,7 @@ innobase_report_binlog_offset_and_commit( trx->mysql_log_file_name = log_file_name; trx->mysql_log_offset = (ib_longlong)end_offset; +#ifdef HAVE_REPLICATION if (thd->variables.sync_replication) { /* Let us store the binlog file name and the position, so that we know how long to wait for the binlog to the replicated to @@ -1628,7 +1629,7 @@ innobase_report_binlog_offset_and_commit( trx->repl_wait_binlog_pos = (ib_longlong)end_offset; } - +#endif /* HAVE_REPLICATION */ trx->flush_log_later = TRUE; innobase_commit(thd, trx_handle); @@ -1681,10 +1682,7 @@ innobase_commit_complete( /* out: 0 */ THD* thd) /* in: user thread */ { - struct timespec abstime; trx_t* trx; - int cmp; - int ret; trx = (trx_t*) thd->ha_data[innobase_hton.slot]; @@ -1700,21 +1698,19 @@ innobase_commit_complete( trx_commit_complete_for_mysql(trx); } - printf("Wait binlog name %s, repl state %lu\n", - trx->repl_wait_binlog_name, - (uint)innobase_repl_state); - +#ifdef HAVE_REPLICATION if (thd->variables.sync_replication && trx->repl_wait_binlog_name && innobase_repl_state != 0) { + struct timespec abstime; + int cmp; + int ret; + /* In synchronous replication, let us wait until the MySQL replication has sent the relevant binlog segment to the replication slave. */ -/* TODO: Make sure MySQL uses some way (TCP_NODELAY?) to ensure that the data -has been received in the slave! */ - pthread_mutex_lock(&innobase_repl_cond_mutex); try_again: if (innobase_repl_state == 0) { @@ -1809,10 +1805,11 @@ try_again: goto try_again; } - +#endif HAVE_REPLICATION return(0); } +#ifdef HAVE_REPLICATION /********************************************************************* In synchronous replication, reports to InnoDB up to which binlog position we have sent the binlog to the slave. Note that replication is synchronous @@ -1908,6 +1905,7 @@ innobase_repl_report_sent_binlog( pthread_cond_broadcast(&innobase_repl_cond); } } +#endif /* HAVE_REPLICATION */ /********************************************************************* Rolls back a transaction or the latest SQL statement. */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f1efe0330db..169c9e057b5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5495,6 +5495,7 @@ The minimum value for this variable is 4096.", {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, +#ifdef HAVE_REPLICATION {"sync-replication", OPT_SYNC_REPLICATION, "Enable synchronous replication.", (gptr*) &global_system_variables.sync_replication, @@ -5510,6 +5511,7 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.sync_replication_timeout, (gptr*) &global_system_variables.sync_replication_timeout, 0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0}, +#endif /* HAVE_REPLICATION */ {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L, From af00b989df825ef5e4bb5ef168e03c65812d3175 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 13:43:02 +0300 Subject: [PATCH 45/47] ha_innodb.cc: Correct an assertion --- sql/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 7d77ae809b1..4052ed14259 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1623,7 +1623,7 @@ innobase_report_binlog_offset_and_commit( (char*)mem_alloc_noninline(FN_REFLEN + 100); } - ut_a(strlen(log_file_name) <= FN_REFLEN + 100); + ut_a(strlen(log_file_name) < FN_REFLEN + 100); strcpy(trx->repl_wait_binlog_name, log_file_name); From 7d6c12313e14b56c7a33eeb438974f5b33d84aab Mon Sep 17 00:00:00 2001 From: "georg@lmy002.wdf.sap.corp" <> Date: Wed, 27 Apr 2005 13:54:42 +0200 Subject: [PATCH 46/47] fix for compile error (Windows) --- sql/item_func.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_func.h b/sql/item_func.h index ba5a6101e4c..77b977fe778 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1318,7 +1318,7 @@ public: longlong val_int() { if (execute(&result_field)) - return 0LL; + return (longlong) 0; return result_field->val_int(); } From ce2c8126a2f6d77b5324771361be2ff3b622bfc1 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 27 Apr 2005 15:09:41 +0300 Subject: [PATCH 47/47] handler.cc: Fix compilation error if HAVE_REPLICATION is not defined --- sql/handler.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/handler.cc b/sql/handler.cc index 95fd4d97616..3095aeb9476 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2412,6 +2412,7 @@ TYPELIB *ha_known_exts(void) return &known_extensions; } +#ifdef HAVE_REPLICATION /* Reports to table handlers up to which position we have sent the binlog to a slave in replication @@ -2468,3 +2469,4 @@ int ha_repl_report_replication_stop(THD *thd) return 0; } +#endif /* HAVE_REPLICATION */