From: Date: August 11 2008 1:30pm Subject: bzr push into mysql-5.1 branch (jonas:2643) Bug#30780 List-Archive: http://lists.mysql.com/commits/51285 X-Bug: 30780 Message-Id: <20080811113053.AB8C3917AD7@perch.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 2643 jonas@stripped 2008-08-11 ndb - bug#30780 DIH: Add rerunning of GCP_NOMORETRANSREQ (if needed) TC: Add handling of various new cases wrt GCP and node failure Add LQHTRANSREQ transactions to GCP-list modified: storage/ndb/src/kernel/blocks/ERROR_codes.txt storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp storage/ndb/src/kernel/vm/SimulatedBlock.cpp storage/ndb/src/kernel/vm/pc.hpp storage/ndb/test/ndbapi/test_event.cpp storage/ndb/test/run-test/daily-basic-tests.txt === modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt' --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2008-05-30 08:03:55 +0000 +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2008-08-11 10:41:11 +0000 @@ -5,7 +5,7 @@ Next DBACC 3002 Next DBTUP 4029 Next DBLQH 5051 Next DBDICT 6008 -Next DBDIH 7211 +Next DBDIH 7215 Next DBTC 8064 Next CMVMI 9000 Next BACKUP 10041 @@ -182,6 +182,9 @@ And crash when all have "not" been sent 7191: Crash when receiving LCP_COMPLETE_REP 7192: Crash in setLcpActiveStatusStart - when dead node missed to LCP's +7213: in GCP_COMMIT Kill specified node and self, stop processing +7214: in GCP_TCFINISHED kill specified node + ERROR CODES FOR TESTING NODE FAILURE, FAILURE IN COPY FRAGMENT PROCESS: ----------------------------------------------------------------------- === modified file 'storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp' --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2008-06-09 10:04:48 +0000 +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2008-08-11 10:41:11 +0000 @@ -5468,6 +5468,21 @@ void Dbdih::execMASTER_GCPREQ(Signal* si case MicroGcp::M_GCP_COMMITTED: jam(); gcpState = MasterGCPConf::GCP_COMMITTED; + + /** + * Change state to GCP_COMMIT_RECEIVEDn and rerun GSN_GCP_NOMORETRANS + */ + gcpState = MasterGCPConf::GCP_COMMIT_RECEIVED; + m_micro_gcp.m_state = MicroGcp::M_GCP_COMMIT; + + { + GCPNoMoreTrans* req2 = (GCPNoMoreTrans*)signal->getDataPtrSend(); + req2->senderData = m_micro_gcp.m_master_ref; + req2->gci_hi = m_micro_gcp.m_old_gci >> 32; + req2->gci_lo = m_micro_gcp.m_old_gci & 0xFFFFFFFF; + sendSignal(clocaltcblockref, GSN_GCP_NOMORETRANS, signal, + GCPNoMoreTrans::SignalLength, JBB); + } break; }; @@ -8726,6 +8741,28 @@ void Dbdih::execGCP_COMMIT(Signal* signa } Uint64 gci = gci_lo | (Uint64(gci_hi) << 32); +#ifdef ERROR_INSERT + if (ERROR_INSERTED(7213)) + { + ndbout_c("err 7213 killing %d", c_error_insert_extra); + Uint32 save = signal->theData[0]; + signal->theData[0] = 5048; + sendSignal(numberToRef(DBLQH, c_error_insert_extra), + GSN_NDB_TAMPER, signal, 1, JBB); + signal->theData[0] = save; + CLEAR_ERROR_INSERT_VALUE; + + signal->theData[0] = 9999; + sendSignal(numberToRef(CMVMI, c_error_insert_extra), + GSN_DUMP_STATE_ORD, signal, 1, JBB); + + signal->theData[0] = save; + CLEAR_ERROR_INSERT_VALUE; + + return; + } +#endif + Uint32 masterRef = calcDihBlockRef(masterNodeId); ndbrequire(masterNodeId = cmasterNodeId); if (isMaster()) @@ -8804,6 +8841,19 @@ void Dbdih::execGCP_TCFINISHED(Signal* s return; } +#ifdef ERROR_INSERT + if (ERROR_INSERTED(7214)) + { + ndbout_c("err 7214 killing %d", c_error_insert_extra); + Uint32 save = signal->theData[0]; + signal->theData[0] = 9999; + sendSignal(numberToRef(CMVMI, c_error_insert_extra), + GSN_NDB_TAMPER, signal, 1, JBB); + signal->theData[0] = save; + CLEAR_ERROR_INSERT_VALUE; + } +#endif + #ifdef GCP_TIMER_HACK NdbTick_getMicroTimer(&globalData.gcp_timer_commit[1]); #endif @@ -15527,6 +15577,19 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal if (signal->theData[0] == 7901) globalData.gcp_timer_limit = signal->theData[1]; #endif + + DECLARE_DUMP0(DBDIH, 7213, "Set error 7213 with extra arg") + { + SET_ERROR_INSERT_VALUE2(7213, signal->theData[1]); + return; + } + + DECLARE_DUMP0(DBDIH, 7214, "Set error 7214 with extra arg") + { + SET_ERROR_INSERT_VALUE2(7214, signal->theData[1]); + return; + } + }//Dbdih::execDUMP_STATE_ORD() void === modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp' --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2008-07-23 11:15:31 +0000 +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2008-08-11 10:41:11 +0000 @@ -6146,9 +6146,8 @@ void Dblqh::execCOMPLETE(Signal* signal) errorReport(signal, 1); return; }//if - if (ERROR_INSERTED(5042)) { - ndbrequire(false); - } + CRASH_INSERTION(5042); + if (ERROR_INSERTED(5013)) { CLEAR_ERROR_INSERT_VALUE; sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3); === modified file 'storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp' --- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2007-12-13 20:34:28 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2008-08-11 10:41:11 +0000 @@ -1431,10 +1431,10 @@ private: void checkGcp(Signal* signal); void commitGciHandling(Signal* signal, Uint64 Tgci); - void copyApi(Signal* signal); + void copyApi(Ptr dst, Ptr src); void DIVER_node_fail_handling(Signal* signal, Uint64 Tgci); - void gcpTcfinished(Signal* signal); - void handleGcp(Signal* signal); + void gcpTcfinished(Signal* signal, Uint64 gci); + void handleGcp(Signal* signal, Ptr); void hash(Signal* signal); bool handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, @@ -1453,8 +1453,8 @@ private: void initialiseScanOprec(Signal* signal); void initTable(Signal* signal); void initialiseTcConnect(Signal* signal); - void linkApiToGcp(Signal* signal); - void linkGciInGcilist(Signal* signal); + void linkApiToGcp(Ptr, Ptr); + void linkGciInGcilist(Ptr); void linkKeybuf(Signal* signal); void linkTcInConnectionlist(Signal* signal); void releaseAbortResources(Signal* signal); @@ -1462,7 +1462,6 @@ private: void releaseApiConCopy(Signal* signal); void releaseApiConnectFail(Signal* signal); void releaseAttrinfo(); - void releaseGcp(Signal* signal); void releaseKeys(); void releaseDirtyRead(Signal*, ApiConnectRecordPtr, TcConnectRecord*); void releaseDirtyWrite(Signal* signal); @@ -1474,10 +1473,10 @@ private: void seizeApiConnectCopy(Signal* signal); void seizeApiConnectFail(Signal* signal); void seizeDatabuf(Signal* signal); - void seizeGcp(Signal* signal); + void seizeGcp(Ptr & dst, Uint64 gci); void seizeTcConnect(Signal* signal); void seizeTcConnectFail(Signal* signal); - void sendApiCommit(Signal* signal); + Ptr sendApiCommit(Signal* signal); void sendAttrinfo(Signal* signal, UintR TattrinfoPtr, AttrbufRecord * const regAttrPtr, @@ -1488,8 +1487,8 @@ private: void sendSystemError(Signal* signal, int line); void sendtckeyconf(Signal* signal, UintR TcommitFlag); void sendTcIndxConf(Signal* signal, UintR TcommitFlag); - void unlinkApiConnect(Signal* signal); - void unlinkGcp(Signal* signal); + void unlinkApiConnect(Ptr, Ptr); + void unlinkGcp(Ptr); void unlinkReadyTcCon(Signal* signal); void handleFailedOperation(Signal* signal, const LqhKeyRef * const lqhKeyRef, @@ -1661,8 +1660,8 @@ private: UintR chostFilesize; NdbNodeBitmask c_alive_nodes; + Uint32 c_ongoing_take_over_cnt; GcpRecord *gcpRecord; - GcpRecordPtr gcpPtr; UintR cgcpFilesize; TableRecord *tableRecord; @@ -1677,7 +1676,6 @@ private: UintR ctcTimer; UintR cDbHbInterval; - ApiConnectRecordPtr tmpApiConnectptr; Uint64 tcheckGcpId; struct TransCounters { === modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp' --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp 2007-02-14 17:26:58 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp 2008-08-11 10:41:11 +0000 @@ -292,6 +292,7 @@ Dbtc::Dbtc(Block_context& ctx): tcFailRecord = 0; c_apiConTimer = 0; c_apiConTimer_line = 0; + c_ongoing_take_over_cnt = 0; #ifdef VM_TRACE { @@ -300,8 +301,6 @@ Dbtc::Dbtc(Block_context& ctx): &cachePtr, &attrbufptr, &hostptr, - &gcpPtr, - &tmpApiConnectptr, &timeOutptr, &scanFragptr, &databufptr, === modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp' --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2008-05-27 19:43:02 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2008-08-11 10:41:11 +0000 @@ -4397,22 +4397,21 @@ void Dbtc::commitGciHandling(Signal* sig UintR TgcpFilesize = cgcpFilesize; UintR Tfirstgcp = cfirstgcp; - ApiConnectRecord * const regApiPtr = apiConnectptr.p; + Ptr regApiPtr = apiConnectptr; GcpRecord *localGcpRecord = gcpRecord; - regApiPtr->globalcheckpointid = Tgci; + regApiPtr.p->globalcheckpointid = Tgci; if (Tfirstgcp != RNIL) { /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */ localGcpPointer.i = Tfirstgcp; ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord); do { - if (regApiPtr->globalcheckpointid == localGcpPointer.p->gcpId) { + if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) { jam(); - gcpPtr.i = localGcpPointer.i; - gcpPtr.p = localGcpPointer.p; - linkApiToGcp(signal); + linkApiToGcp(localGcpPointer, regApiPtr); return; } else { + ndbrequire(regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId); localGcpPointer.i = localGcpPointer.p->nextGcp; jam(); if (localGcpPointer.i != RNIL) { @@ -4421,14 +4420,14 @@ void Dbtc::commitGciHandling(Signal* sig continue; }//if }//if - seizeGcp(signal); - linkApiToGcp(signal); + seizeGcp(localGcpPointer, Tgci); + linkApiToGcp(localGcpPointer, regApiPtr); return; } while (1); } else { jam(); - seizeGcp(signal); - linkApiToGcp(signal); + seizeGcp(localGcpPointer, Tgci); + linkApiToGcp(localGcpPointer, regApiPtr); }//if }//Dbtc::commitGciHandling() @@ -4437,46 +4436,43 @@ void Dbtc::commitGciHandling(Signal* sig /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS */ /* LINKED OUT OF THE LIST. */ /*---------------------------------------------------------------------------*/ -void Dbtc::linkApiToGcp(Signal* signal) +void Dbtc::linkApiToGcp(Ptr regGcpPtr, + Ptr regApiPtr) { ApiConnectRecordPtr localApiConnectptr; - ApiConnectRecord * const regApiPtr = apiConnectptr.p; - GcpRecord * const regGcpPtr = gcpPtr.p; - UintR TapiConnectptrIndex = apiConnectptr.i; ApiConnectRecord *localApiConnectRecord = apiConnectRecord; - regApiPtr->nextGcpConnect = RNIL; - if (regGcpPtr->firstApiConnect == RNIL) { - regGcpPtr->firstApiConnect = TapiConnectptrIndex; + regApiPtr.p->nextGcpConnect = RNIL; + if (regGcpPtr.p->firstApiConnect == RNIL) { + regGcpPtr.p->firstApiConnect = regApiPtr.i; jam(); } else { UintR TapiConnectFilesize = capiConnectFilesize; - localApiConnectptr.i = regGcpPtr->lastApiConnect; + localApiConnectptr.i = regGcpPtr.p->lastApiConnect; jam(); ptrCheckGuard(localApiConnectptr, TapiConnectFilesize, localApiConnectRecord); - localApiConnectptr.p->nextGcpConnect = TapiConnectptrIndex; + localApiConnectptr.p->nextGcpConnect = regApiPtr.i; }//if - UintR TlastApiConnect = regGcpPtr->lastApiConnect; - regApiPtr->gcpPointer = gcpPtr.i; - regApiPtr->prevGcpConnect = TlastApiConnect; - regGcpPtr->lastApiConnect = TapiConnectptrIndex; + UintR TlastApiConnect = regGcpPtr.p->lastApiConnect; + regApiPtr.p->gcpPointer = regGcpPtr.i; + regApiPtr.p->prevGcpConnect = TlastApiConnect; + regGcpPtr.p->lastApiConnect = regApiPtr.i; }//Dbtc::linkApiToGcp() -void Dbtc::seizeGcp(Signal* signal) +void Dbtc::seizeGcp(Ptr & dst, Uint64 Tgci) { GcpRecordPtr tmpGcpPointer; GcpRecordPtr localGcpPointer; UintR Tfirstgcp = cfirstgcp; - Uint64 Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid; UintR TgcpFilesize = cgcpFilesize; GcpRecord *localGcpRecord = gcpRecord; localGcpPointer.i = cfirstfreeGcp; ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord); UintR TfirstfreeGcp = localGcpPointer.p->nextGcp; - localGcpPointer.p->gcpId = Tglobalcheckpointid; + localGcpPointer.p->gcpId = Tgci; localGcpPointer.p->nextGcp = RNIL; localGcpPointer.p->firstApiConnect = RNIL; localGcpPointer.p->lastApiConnect = RNIL; @@ -4493,7 +4489,7 @@ void Dbtc::seizeGcp(Signal* signal) tmpGcpPointer.p->nextGcp = localGcpPointer.i; }//if clastgcp = localGcpPointer.i; - gcpPtr = localGcpPointer; + dst = localGcpPointer; }//Dbtc::seizeGcp() /*---------------------------------------------------------------------------*/ @@ -4621,6 +4617,7 @@ void Dbtc::execCOMMITTED(Signal* signal) { TcConnectRecordPtr localTcConnectptr; ApiConnectRecordPtr localApiConnectptr; + ApiConnectRecordPtr localCopyPtr; UintR TtcConnectFilesize = ctcConnectFilesize; UintR TapiConnectFilesize = capiConnectFilesize; @@ -4696,14 +4693,14 @@ void Dbtc::execCOMMITTED(Signal* signal) /*-------------------------------------------------------*/ apiConnectptr = localApiConnectptr; - sendApiCommit(signal); + localCopyPtr = sendApiCommit(signal); - ApiConnectRecord * const regApiPtr = apiConnectptr.p; - localTcConnectptr.i = regApiPtr->firstTcConnect; - UintR Tlqhkeyconfrec = regApiPtr->lqhkeyconfrec; + localTcConnectptr.i = localCopyPtr.p->firstTcConnect; + UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec; ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord); - regApiPtr->counter = Tlqhkeyconfrec; + localCopyPtr.p->counter = Tlqhkeyconfrec; + apiConnectptr = localCopyPtr; tcConnectptr = localTcConnectptr; complete010Lab(signal); return; @@ -4714,9 +4711,10 @@ void Dbtc::execCOMMITTED(Signal* signal) /* SEND_API_COMMIT */ /* SEND COMMIT DECISION TO THE API. */ /*-------------------------------------------------------*/ -void Dbtc::sendApiCommit(Signal* signal) +Ptr +Dbtc::sendApiCommit(Signal* signal) { - ApiConnectRecord * const regApiPtr = apiConnectptr.p; + ApiConnectRecordPtr regApiPtr = apiConnectptr; if (ERROR_INSERTED(8055)) { @@ -4728,58 +4726,59 @@ void Dbtc::sendApiCommit(Signal* signal) signal->theData[0] = 9999; sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1); - Uint32 node = refToNode(regApiPtr->ndbapiBlockref); + Uint32 node = refToNode(regApiPtr.p->ndbapiBlockref); signal->theData[0] = node; sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB); SET_ERROR_INSERT_VALUE(8056); - return; + + Ptr copyPtr; + copyPtr.i = regApiPtr.p->apiCopyRecord; + ptrCheckGuard(copyPtr, capiConnectFilesize, apiConnectRecord); + return copyPtr; } - if (regApiPtr->returnsignal == RS_TCKEYCONF) { + if (regApiPtr.p->returnsignal == RS_TCKEYCONF) { sendtckeyconf(signal, 1); - } else if (regApiPtr->returnsignal == RS_TC_COMMITCONF) { + } else if (regApiPtr.p->returnsignal == RS_TC_COMMITCONF) { jam(); TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0]; - if(regApiPtr->commitAckMarker == RNIL){ + if(regApiPtr.p->commitAckMarker == RNIL){ jam(); - commitConf->apiConnectPtr = regApiPtr->ndbapiConnect; + commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect; } else { jam(); - commitConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1; + commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect | 1; } - commitConf->transId1 = regApiPtr->transid[0]; - commitConf->transId2 = regApiPtr->transid[1]; - commitConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32); - commitConf->gci_lo = Uint32(regApiPtr->globalcheckpointid); + commitConf->transId1 = regApiPtr.p->transid[0]; + commitConf->transId2 = regApiPtr.p->transid[1]; + commitConf->gci_hi = Uint32(regApiPtr.p->globalcheckpointid >> 32); + commitConf->gci_lo = Uint32(regApiPtr.p->globalcheckpointid); - sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal, + sendSignal(regApiPtr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal, TcCommitConf::SignalLength, JBB); - } else if (regApiPtr->returnsignal == RS_NO_RETURN) { + } else if (regApiPtr.p->returnsignal == RS_NO_RETURN) { jam(); } else { TCKEY_abort(signal, 37); - return; + return regApiPtr; }//if + Ptr copyPtr; UintR TapiConnectFilesize = capiConnectFilesize; UintR TcommitCount = c_counters.ccommitCount; - UintR TapiIndex = apiConnectptr.i; - UintR TnewApiIndex = regApiPtr->apiCopyRecord; - UintR TapiFailState = regApiPtr->apiFailState; + copyPtr.i = regApiPtr.p->apiCopyRecord; + UintR TapiFailState = regApiPtr.p->apiFailState; ApiConnectRecord *localApiConnectRecord = apiConnectRecord; - tmpApiConnectptr.p = apiConnectptr.p; - tmpApiConnectptr.i = TapiIndex; c_counters.ccommitCount = TcommitCount + 1; - apiConnectptr.i = TnewApiIndex; - ptrCheckGuard(apiConnectptr, TapiConnectFilesize, localApiConnectRecord); - copyApi(signal); + ptrCheckGuard(copyPtr, TapiConnectFilesize, localApiConnectRecord); + copyApi(copyPtr, regApiPtr); if (TapiFailState != ZTRUE) { - return; + return copyPtr; } else { jam(); - handleApiFailState(signal, tmpApiConnectptr.i); - return; + handleApiFailState(signal, regApiPtr.i); + return copyPtr; }//if }//Dbtc::sendApiCommit() @@ -4788,54 +4787,52 @@ void Dbtc::sendApiCommit(Signal* signal) /* COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT */ /* IS PREPARED TO RECEIVE A NEW TRANSACTION. */ /*===========================================================================*/ -void Dbtc::copyApi(Signal* signal) +void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr) { - ApiConnectRecord * const regApiPtr = apiConnectptr.p; - ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p; - - UintR TndbapiConnect = regTmpApiPtr->ndbapiConnect; - UintR TfirstTcConnect = regTmpApiPtr->firstTcConnect; - UintR Ttransid1 = regTmpApiPtr->transid[0]; - UintR Ttransid2 = regTmpApiPtr->transid[1]; - UintR Tlqhkeyconfrec = regTmpApiPtr->lqhkeyconfrec; - UintR TgcpPointer = regTmpApiPtr->gcpPointer; + UintR TndbapiConnect = regApiPtr.p->ndbapiConnect; + UintR TfirstTcConnect = regApiPtr.p->firstTcConnect; + UintR Ttransid1 = regApiPtr.p->transid[0]; + UintR Ttransid2 = regApiPtr.p->transid[1]; + UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec; + UintR TgcpPointer = regApiPtr.p->gcpPointer; UintR TgcpFilesize = cgcpFilesize; - UintR TcommitAckMarker = regTmpApiPtr->commitAckMarker; - NdbNodeBitmask Tnodes = regTmpApiPtr->m_transaction_nodes; + UintR TcommitAckMarker = regApiPtr.p->commitAckMarker; + NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes; GcpRecord *localGcpRecord = gcpRecord; - regApiPtr->ndbapiBlockref = regTmpApiPtr->ndbapiBlockref; - regApiPtr->ndbapiConnect = TndbapiConnect; - regApiPtr->firstTcConnect = TfirstTcConnect; - regApiPtr->apiConnectstate = CS_COMPLETING; - regApiPtr->transid[0] = Ttransid1; - regApiPtr->transid[1] = Ttransid2; - regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec; - regApiPtr->commitAckMarker = TcommitAckMarker; - regApiPtr->m_transaction_nodes = Tnodes; - regApiPtr->singleUserMode = 0; + copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref; + copyPtr.p->ndbapiConnect = TndbapiConnect; + copyPtr.p->firstTcConnect = TfirstTcConnect; + copyPtr.p->apiConnectstate = CS_COMPLETING; + copyPtr.p->transid[0] = Ttransid1; + copyPtr.p->transid[1] = Ttransid2; + copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec; + copyPtr.p->commitAckMarker = TcommitAckMarker; + copyPtr.p->m_transaction_nodes = Tnodes; + copyPtr.p->singleUserMode = 0; + Ptr gcpPtr; gcpPtr.i = TgcpPointer; ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord); - unlinkApiConnect(signal); - linkApiToGcp(signal); - setApiConTimer(tmpApiConnectptr.i, 0, __LINE__); - regTmpApiPtr->apiConnectstate = CS_CONNECTED; - regTmpApiPtr->commitAckMarker = RNIL; - regTmpApiPtr->firstTcConnect = RNIL; - regTmpApiPtr->lastTcConnect = RNIL; - regTmpApiPtr->m_transaction_nodes.clear(); - regTmpApiPtr->singleUserMode = 0; - releaseAllSeizedIndexOperations(regTmpApiPtr); + unlinkApiConnect(gcpPtr, regApiPtr); + linkApiToGcp(gcpPtr, copyPtr); + setApiConTimer(regApiPtr.i, 0, __LINE__); + regApiPtr.p->apiConnectstate = CS_CONNECTED; + regApiPtr.p->commitAckMarker = RNIL; + regApiPtr.p->firstTcConnect = RNIL; + regApiPtr.p->lastTcConnect = RNIL; + regApiPtr.p->m_transaction_nodes.clear(); + regApiPtr.p->singleUserMode = 0; + releaseAllSeizedIndexOperations(regApiPtr.p); }//Dbtc::copyApi() -void Dbtc::unlinkApiConnect(Signal* signal) +void Dbtc::unlinkApiConnect(Ptr gcpPtr, + Ptr regApiPtr) { ApiConnectRecordPtr localApiConnectptr; - ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p; UintR TapiConnectFilesize = capiConnectFilesize; - UintR TprevGcpConnect = regTmpApiPtr->prevGcpConnect; - UintR TnextGcpConnect = regTmpApiPtr->nextGcpConnect; + UintR TprevGcpConnect = regApiPtr.p->prevGcpConnect; + UintR TnextGcpConnect = regApiPtr.p->nextGcpConnect; ApiConnectRecord *localApiConnectRecord = apiConnectRecord; if (TprevGcpConnect == RNIL) { @@ -5096,7 +5093,7 @@ void Dbtc::releaseTransResources(Signal* localTcConnectptr.i = rtrTcConnectptrIndex; releaseTcCon(); } while (localTcConnectptr.i != RNIL); - handleGcp(signal); + handleGcp(signal, apiConnectptr); releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers); releaseAllSeizedIndexOperations(apiConnectptr.p); releaseApiConCopy(signal); @@ -5109,27 +5106,24 @@ void Dbtc::releaseTransResources(Signal* /* SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */ /* GLOBAL CHECKPOINT HAVE COMPLETED. */ /* *********************************************************************>> */ -void Dbtc::handleGcp(Signal* signal) +void Dbtc::handleGcp(Signal* signal, Ptr regApiPtr) { GcpRecord *localGcpRecord = gcpRecord; GcpRecordPtr localGcpPtr; - UintR TapiConnectptrIndex = apiConnectptr.i; UintR TgcpFilesize = cgcpFilesize; localGcpPtr.i = apiConnectptr.p->gcpPointer; - tmpApiConnectptr.i = TapiConnectptrIndex; - tmpApiConnectptr.p = apiConnectptr.p; ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord); - gcpPtr.i = localGcpPtr.i; - gcpPtr.p = localGcpPtr.p; - unlinkApiConnect(signal); + unlinkApiConnect(localGcpPtr, regApiPtr); if (localGcpPtr.p->firstApiConnect == RNIL) { if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) { - jam(); - tcheckGcpId = localGcpPtr.p->gcpId; - gcpTcfinished(signal); - unlinkGcp(signal); + if (c_ongoing_take_over_cnt == 0) + { + jam(); + gcpTcfinished(signal, localGcpPtr.p->gcpId); + unlinkGcp(localGcpPtr); + } }//if - }//if + } }//Dbtc::handleGcp() void Dbtc::releaseApiConCopy(Signal* signal) @@ -7124,35 +7118,136 @@ void Dbtc::execGCP_NOMORETRANS(Signal* s Uint32 gci_lo = req->gci_lo; Uint32 gci_hi = req->gci_hi; tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32); + + Ptr gcpPtr; if (cfirstgcp != RNIL) { jam(); /* A GLOBAL CHECKPOINT IS GOING ON */ gcpPtr.i = cfirstgcp; /* SET POINTER TO FIRST GCP IN QUEUE*/ ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord); - if (gcpPtr.p->gcpId == tcheckGcpId) { + if (gcpPtr.p->gcpId == tcheckGcpId) + { jam(); - if (gcpPtr.p->firstApiConnect != RNIL) { + bool empty = gcpPtr.p->firstApiConnect == RNIL; + bool nfhandling = c_ongoing_take_over_cnt; + + if (empty && nfhandling) + { + jam(); + ndbout_c("NOT returning gcpTcfinished due to nfhandling %u/%u", + gci_hi, gci_lo); + } + + if (!empty || c_ongoing_take_over_cnt) + { jam(); gcpPtr.p->gcpNomoretransRec = ZTRUE; } else { jam(); - gcpTcfinished(signal); - unlinkGcp(signal); + gcpTcfinished(signal, tcheckGcpId); + unlinkGcp(gcpPtr); }//if - } else { + } + else if (c_ongoing_take_over_cnt == 0) + { jam(); /*------------------------------------------------------------*/ /* IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO */ /* RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE */ /* THE GLOBAL CHECKPOINTS IN ORDER. */ /*------------------------------------------------------------*/ - gcpTcfinished(signal); - }//if - } else { + gcpTcfinished(signal, tcheckGcpId); + } + else + { + jam(); + goto outoforder; + } + } + else if (c_ongoing_take_over_cnt == 0) + { jam(); - gcpTcfinished(signal); - }//if + gcpTcfinished(signal, tcheckGcpId); + } + else + { +seize: + jam(); + ndbout_c("execGCP_NOMORETRANS(%u/%u) c_ongoing_take_over_cnt -> seize", + gci_hi, gci_lo); + seizeGcp(gcpPtr, tcheckGcpId); + gcpPtr.p->gcpNomoretransRec = ZTRUE; + } return; + +outoforder: + printf("ooo: execGCP_NOMORETRANS tcheckGcpId: %u/%u cfirstgcp: %u/%u", + gci_hi, gci_lo, + Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId)); + + if (tcheckGcpId < gcpPtr.p->gcpId) + { + jam(); + + Ptr tmp; + tmp.i = cfirstfreeGcp; + ptrCheckGuard(tmp, cgcpFilesize, gcpRecord); + cfirstfreeGcp = tmp.p->nextGcp; + + tmp.p->gcpId = tcheckGcpId; + tmp.p->nextGcp = cfirstgcp; + tmp.p->firstApiConnect = RNIL; + tmp.p->lastApiConnect = RNIL; + tmp.p->gcpNomoretransRec = ZTRUE; + cfirstgcp = tmp.i; + ndbout_c("LINK FIRST"); + return; + } + else + { + Ptr prev = gcpPtr; + while (tcheckGcpId > gcpPtr.p->gcpId) + { + jam(); + if (gcpPtr.p->nextGcp == RNIL) + { + printf("nextGcp == RNIL -> "); + goto seize; + } + + prev = gcpPtr; + gcpPtr.i = gcpPtr.p->nextGcp; + ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord); + } + + if (tcheckGcpId == gcpPtr.p->gcpId) + { + jam(); + gcpPtr.p->gcpNomoretransRec = ZTRUE; + ndbout_c("found"); + return; + } + ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<" + ndbrequire(prev.p->gcpId < tcheckGcpId); + ndbrequire(gcpPtr.p->gcpId > tcheckGcpId); + + Ptr tmp; + tmp.i = cfirstfreeGcp; + ptrCheckGuard(tmp, cgcpFilesize, gcpRecord); + cfirstfreeGcp = tmp.p->nextGcp; + + tmp.p->gcpId = tcheckGcpId; + tmp.p->nextGcp = gcpPtr.i; + tmp.p->firstApiConnect = RNIL; + tmp.p->lastApiConnect = RNIL; + tmp.p->gcpNomoretransRec = ZTRUE; + prev.p->nextGcp = tmp.i; + ndbout_c("link middle %u/%u < %u/%u < %u/%u", + Uint32(prev.p->gcpId >> 32), Uint32(prev.p->gcpId), + gci_hi, gci_lo, + Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId)); + return; + } }//Dbtc::execGCP_NOMORETRANS() /*****************************************************************************/ @@ -7210,6 +7305,7 @@ void Dbtc::execNODE_FAILREP(Signal* sign /*------------------------------------------------------------*/ hostptr.p->hostStatus = HS_DEAD; hostptr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS; + c_ongoing_take_over_cnt++; c_alive_nodes.clear(hostptr.i); if (tcNodeFailptr.p->failStatus == FS_LISTENING) @@ -7413,8 +7509,31 @@ void Dbtc::execTAKE_OVERTCCONF(Signal* s tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1]; tcNodeFailptr.p->queueIndex = end - 1; } - + + Uint32 cnt = c_ongoing_take_over_cnt; + ndbrequire(cnt); + c_ongoing_take_over_cnt = cnt - 1; checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER); + + if (cnt == 1 && cfirstgcp != RNIL) + { + /** + * Check if there are any hanging GCP_NOMORETRANS + */ + GcpRecordPtr tmpGcpPointer; + tmpGcpPointer.i = cfirstgcp; + ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord); + if (tmpGcpPointer.p->gcpNomoretransRec && + tmpGcpPointer.p->firstApiConnect == RNIL) + { + jam(); + ndbout_c("completing gcp %u/%u in execTAKE_OVERTCCONF", + Uint32(tmpGcpPointer.p->gcpId >> 32), + Uint32(tmpGcpPointer.p->gcpId)); + gcpTcfinished(signal, tmpGcpPointer.p->gcpId); + unlinkGcp(tmpGcpPointer); + } + } }//Dbtc::execTAKE_OVERTCCONF() void Dbtc::execTAKE_OVERTCREQ(Signal* signal) @@ -7466,7 +7585,16 @@ void Dbtc::startTakeOverLab(Signal* sign signal->theData[0] = tcNodeFailptr.i; signal->theData[1] = cownref; signal->theData[2] = tfailedNodeId; - sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB); + if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId()) + { + ndbout_c("sending delayed GSN_LQH_TRANSREQ to self"); + sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, 3); + CLEAR_ERROR_INSERT_VALUE; + } + else + { + sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB); + } }//if }//for }//Dbtc::startTakeOverLab() @@ -7720,6 +7848,7 @@ void Dbtc::completeTransAtTakeOverDoOne( apiConnectptr.p->currentTcConnect = tcConnectptr.i; apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo; tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo; + commitGciHandling(signal, apiConnectptr.p->globalcheckpointid); toCompleteHandlingLab(signal); return; case CS_FAIL_COMMITTING: @@ -7734,6 +7863,7 @@ void Dbtc::completeTransAtTakeOverDoOne( apiConnectptr.p->currentTcConnect = tcConnectptr.i; apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo; tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo; + commitGciHandling(signal, apiConnectptr.p->globalcheckpointid); toCommitHandlingLab(signal); return; case CS_FAIL_ABORTING: @@ -8199,7 +8329,7 @@ void Dbtc::toCommitHandlingLab(Signal* s sendTCKEY_FAILCONF(signal, apiConnectptr.p); } else { jam(); - sendApiCommit(signal); + apiConnectptr = sendApiCommit(signal); }//if apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect; tcConnectptr.i = apiConnectptr.p->firstTcConnect; @@ -8335,6 +8465,7 @@ void Dbtc::toCompleteHandlingLab(Signal* signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec; signal->theData[2] = apiConnectptr.p->takeOverInd; sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB); + handleGcp(signal, apiConnectptr); releaseTakeOver(signal); } else { jam(); @@ -10335,12 +10466,12 @@ void Dbtc::sendScanTabConf(Signal* signa }//Dbtc::sendScanTabConf() -void Dbtc::gcpTcfinished(Signal* signal) +void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci) { GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend(); conf->senderData = c_gcp_ref; - conf->gci_hi = Uint32(tcheckGcpId >> 32); - conf->gci_lo = Uint32(tcheckGcpId); + conf->gci_hi = Uint32(gci >> 32); + conf->gci_lo = Uint32(gci); sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, GCPTCFinished::SignalLength, JBB); }//Dbtc::gcpTcfinished() @@ -10486,6 +10617,7 @@ void Dbtc::initdatabuf(Signal* signal) void Dbtc::initgcp(Signal* signal) { + Ptr gcpPtr; ndbrequire(cgcpFilesize > 0); for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) { ptrAss(gcpPtr, gcpRecord); @@ -10687,7 +10819,7 @@ void Dbtc::initialiseTcConnect(Signal* s /* ---- LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS */ /* WAITING FOR COMPLETION. */ /* ------------------------------------------------------------------------- */ -void Dbtc::linkGciInGcilist(Signal* signal) +void Dbtc::linkGciInGcilist(Ptr gcpPtr) { GcpRecordPtr tmpGcpPointer; if (cfirstgcp == RNIL) { @@ -10860,13 +10992,6 @@ void Dbtc::releaseApiConnectFail(Signal* cfirstfreeApiConnectFail = apiConnectptr.i; }//Dbtc::releaseApiConnectFail() -void Dbtc::releaseGcp(Signal* signal) -{ - ptrGuard(gcpPtr); - gcpPtr.p->nextGcp = cfirstfreeGcp; - cfirstfreeGcp = gcpPtr.i; -}//Dbtc::releaseGcp() - void Dbtc::releaseKeys() { UintR Tmp; @@ -11059,25 +11184,18 @@ void Dbtc::sendSystemError(Signal* signa /* ========================================================================= */ /* ------- LINK ACTUAL GCP OUT OF LIST ------- */ /* ------------------------------------------------------------------------- */ -void Dbtc::unlinkGcp(Signal* signal) +void Dbtc::unlinkGcp(Ptr tmpGcpPtr) { - if (cfirstgcp == gcpPtr.i) { - jam(); - cfirstgcp = gcpPtr.p->nextGcp; - if (gcpPtr.i == clastgcp) { - jam(); - clastgcp = RNIL; - }//if - } else { + ndbrequire(cfirstgcp == tmpGcpPtr.i); + + cfirstgcp = tmpGcpPtr.p->nextGcp; + if (tmpGcpPtr.i == clastgcp) { jam(); - /* -------------------------------------------------------------------- - * WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST. - * THIS IS A SYSTEM ERROR. - * ------------------------------------------------------------------- */ - sendSystemError(signal, __LINE__); + clastgcp = RNIL; }//if - gcpPtr.p->nextGcp = cfirstfreeGcp; - cfirstfreeGcp = gcpPtr.i; + + tmpGcpPtr.p->nextGcp = cfirstfreeGcp; + cfirstfreeGcp = tmpGcpPtr.i; }//Dbtc::unlinkGcp() void === modified file 'storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp' --- a/storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp 2008-04-25 09:17:15 +0000 +++ b/storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp 2008-08-11 10:41:11 +0000 @@ -383,10 +383,6 @@ private: void execREAD_CONFIG_CONF(Signal*); friend struct UpgradeStartup; - -#ifdef ERROR_INSERT - Uint32 c_error_insert_extra; -#endif }; #endif === modified file 'storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp' --- a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp 2008-04-25 09:17:15 +0000 +++ b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp 2008-08-11 10:41:11 +0000 @@ -456,10 +456,6 @@ private: StopReq c_stopReq; bool check_multi_node_shutdown(Signal* signal); -#ifdef ERROR_INSERT - Uint32 c_error_insert_extra; -#endif - void recompute_version_info(Uint32 type); void recompute_version_info(Uint32 type, Uint32 version); void execNODE_VERSION_REP(Signal* signal); === modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.cpp' --- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2008-04-22 19:36:05 +0000 +++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2008-08-11 10:41:11 +0000 @@ -878,7 +878,14 @@ SimulatedBlock::execCHANGE_NODE_STATE_RE void SimulatedBlock::execNDB_TAMPER(Signal * signal){ - SET_ERROR_INSERT_VALUE(signal->theData[0]); + if (signal->getLength() == 1) + { + SET_ERROR_INSERT_VALUE(signal->theData[0]); + } + else + { + SET_ERROR_INSERT_VALUE2(signal->theData[0], signal->theData[1]); + } } void === modified file 'storage/ndb/src/kernel/vm/pc.hpp' --- a/storage/ndb/src/kernel/vm/pc.hpp 2008-02-04 13:36:54 +0000 +++ b/storage/ndb/src/kernel/vm/pc.hpp 2008-08-11 10:41:11 +0000 @@ -122,19 +122,23 @@ // -------- ERROR INSERT MACROS ------- #ifdef ERROR_INSERT -#define ERROR_INSERT_VARIABLE UintR cerrorInsert +#define ERROR_INSERT_VARIABLE UintR cerrorInsert, c_error_insert_extra #define ERROR_INSERTED(x) (cerrorInsert == (x)) #define ERROR_INSERTED_CLEAR(x) (cerrorInsert == (x) ? (cerrorInsert = 0, true) : false) #define SET_ERROR_INSERT_VALUE(x) cerrorInsert = x +#define SET_ERROR_INSERT_VALUE2(x,y) cerrorInsert = x; c_error_insert_extra = y #define CLEAR_ERROR_INSERT_VALUE cerrorInsert = 0 #else #define ERROR_INSERT_VARIABLE typedef void * cerrorInsert // Will generate compiler error if used #define ERROR_INSERTED(x) false #define ERROR_INSERTED_CLEAR(x) false #define SET_ERROR_INSERT_VALUE(x) +#define SET_ERROR_INSERT_VALUE2(x,y) #define CLEAR_ERROR_INSERT_VALUE #endif +#define DECLARE_DUMP0(BLOCK, CODE, DESC) if (arg == CODE) + /* ------------------------------------------------------------------------- */ /* COMMONLY USED CONSTANTS. */ /* ------------------------------------------------------------------------- */ === modified file 'storage/ndb/test/ndbapi/test_event.cpp' --- a/storage/ndb/test/ndbapi/test_event.cpp 2008-08-04 15:49:01 +0000 +++ b/storage/ndb/test/ndbapi/test_event.cpp 2008-08-11 10:41:11 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() @@ -858,6 +859,82 @@ end: DBUG_RETURN(result); } +int runEventConsumer(NDBT_Context* ctx, NDBT_Step* step) +{ + DBUG_ENTER("runEventConsumer"); + int result = NDBT_OK; + const NdbDictionary::Table * table= ctx->getTab(); + HugoTransactions hugoTrans(* table); + + char buf[1024]; + sprintf(buf, "%s_EVENT", table->getName()); + NdbEventOperation *pOp, *pCreate = 0; + pCreate = pOp = GETNDB(step)->createEventOperation(buf); + if ( pOp == NULL ) { + g_err << "Event operation creation failed on %s" << buf << endl; + DBUG_RETURN(NDBT_FAILED); + } + bool merge_events = ctx->getProperty("MergeEvents"); + pOp->mergeEvents(merge_events); + + int i; + int n_columns= table->getNoOfColumns(); + NdbRecAttr* recAttr[1024]; + NdbRecAttr* recAttrPre[1024]; + for (i = 0; i < n_columns; i++) { + recAttr[i] = pOp->getValue(table->getColumn(i)->getName()); + recAttrPre[i] = pOp->getPreValue(table->getColumn(i)->getName()); + } + + if (pOp->execute()) { // This starts changes to "start flowing" + g_err << "execute operation execution failed: \n"; + g_err << pOp->getNdbError().code << " " + << pOp->getNdbError().message << endl; + result = NDBT_FAILED; + goto end; + } + + ctx->setProperty("LastGCI_hi", ~(Uint32)0); + ctx->broadcast(); + + while(!ctx->isTestStopped()) + { + int count= 0; + Ndb* ndb= GETNDB(step); + + Uint64 last_gci = 0; + while(!ctx->isTestStopped()) + { + Uint32 count = 0; + Uint64 curr_gci; + ndb->pollEvents(100, &curr_gci); + if (curr_gci != last_gci) + { + while ((pOp= ndb->nextEvent()) != 0) + { + count++; + } + last_gci = curr_gci; + } + ndbout_c("Consumed gci: %u/%u, %d events", + Uint32(last_gci >> 32), Uint32(last_gci), count); + } + } + +end: + if(pCreate) + { + if (GETNDB(step)->dropEventOperation(pCreate)) { + g_err << "dropEventOperation execution failed " + << GETNDB(step)->getNdbError().code << " " + << GETNDB(step)->getNdbError().message << endl; + result = NDBT_FAILED; + } + } + ctx->stopTest(); + DBUG_RETURN(result); +} + int runEventListenerUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { @@ -1745,6 +1822,17 @@ runSubscribeUnsubscribe(NDBT_Context* ct return NDBT_OK; } +int +runLoadTable(NDBT_Context* ctx, NDBT_Step* step) +{ + int records = ctx->getNumRecords(); + HugoTransactions hugoTrans(*ctx->getTab()); + if (hugoTrans.loadTable(GETNDB(step), records) != 0){ + return NDBT_FAILED; + } + return NDBT_OK; +} + int runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){ int records = ctx->getNumRecords(); @@ -3039,6 +3127,83 @@ runBug37672(NDBT_Context* ctx, NDBT_Step } +int +runBug30780(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + + NdbRestarter res; + + if (res.getNumDbNodes() < 2) + { + ctx->stopTest(); + return NDBT_OK; + } + + const int cases = 4; + int loops = ctx->getNumLoops(); + if (loops <= cases) + loops = cases + 1; + for (int i = 0; istopTest(); + return NDBT_OK; +} + NDBT_TESTSUITE(test_event); TESTCASE("BasicEventOperation", "Verify that we can listen to Events" @@ -3234,6 +3399,15 @@ TESTCASE("Bug37672", "NdbRecord option O { INITIALIZER(runBug37672); } +TESTCASE("Bug30780", "") +{ + INITIALIZER(runCreateEvent); + INITIALIZER(runLoadTable); + STEP(runEventConsumer); + STEPS(runScanUpdateUntilStopped, 3); + STEP(runBug30780); + FINALIZER(runDropEvent); +} NDBT_TESTSUITE_END(test_event); int main(int argc, const char** argv){ === modified file 'storage/ndb/test/run-test/daily-basic-tests.txt' --- a/storage/ndb/test/run-test/daily-basic-tests.txt 2008-08-06 15:33:19 +0000 +++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2008-08-11 10:41:11 +0000 @@ -1161,3 +1161,9 @@ cmd: testScanFilter args: #EOF 2008-07-09 + +max-time: 600 +cmd: test_event +args -r 5000 -n Bug30780 T1 + +#EOF 2008-08-11