=== modified file 'storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp' --- storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2009-09-01 11:42:04 +0000 +++ storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2009-09-03 09:08:05 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,7 @@ Cmvmi::Cmvmi(Block_context& ctx) : addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true); addRecSignal(GSN_CONTINUEB, &Cmvmi::execCONTINUEB); + addRecSignal(GSN_ROUTE_ORD, &Cmvmi::execROUTE_ORD); subscriberPool.setSize(5); @@ -1728,3 +1730,65 @@ Cmvmi::reportDMUsage(Signal* signal, int signal->theData[5] = DBTUP; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB); } + + +/** + * execROUTE_ORD + * Allows other blocks to route signals as if they + * came from Cmvmi + * Useful in ndbmtd for synchronising signals w.r.t + * external signals received from other nodes which + * arrive from the same thread that runs CMVMI. + */ +void +Cmvmi::execROUTE_ORD(Signal* signal) +{ + jamEntry(); + if(!assembleFragments(signal)){ + jam(); + return; + } + + SectionHandle handle(this, signal); + + RouteOrd* ord = (RouteOrd*)signal->getDataPtr(); + Uint32 dstRef = ord->dstRef; + Uint32 srcRef = ord->srcRef; + Uint32 gsn = ord->gsn; + /* ord->cnt ignored */ + + Uint32 nodeId = refToNode(dstRef); + + if (likely((nodeId == 0) || + getNodeInfo(nodeId).m_connected)) + { + jam(); + Uint32 secCount = handle.m_cnt; + ndbrequire(secCount >= 1 && secCount <= 3); + + jamLine(secCount); + + /** + * Put section 0 in signal->theData + */ + Uint32 sigLen = handle.m_ptr[0].sz; + ndbrequire(sigLen <= 25); + copy(signal->theData, handle.m_ptr[0]); + + SegmentedSectionPtr save = handle.m_ptr[0]; + for (Uint32 i = 0; i < secCount - 1; i++) + handle.m_ptr[i] = handle.m_ptr[i+1]; + handle.m_cnt--; + + sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle); + + handle.m_cnt = 1; + handle.m_ptr[0] = save; + releaseSections(handle); + return ; + } + + releaseSections(handle); + warningEvent("Unable to route GSN: %d from %x to %x", + gsn, srcRef, dstRef); +} === modified file 'storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp' --- storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp 2009-05-27 15:21:45 +0000 +++ storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp 2009-09-03 08:47:10 +0000 @@ -71,6 +71,8 @@ private: void execNODE_START_REP(Signal* signal); void execCONTINUEB(Signal* signal); + + void execROUTE_ORD(Signal* signal); char theErrorMessage[256]; void sendSTTORRY(Signal* signal); === modified file 'storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp' --- storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp 2009-09-01 11:42:04 +0000 +++ storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp 2009-09-03 08:48:26 +0000 @@ -324,7 +324,7 @@ private: void initData(Signal* signal); void sendCloseComReq(Signal* signal, BlockReference TBRef, Uint16 TfailNo); void sendPrepFailReq(Signal* signal, Uint16 aNode); - void sendApiFailReq(Signal* signal, Uint16 aFailedNode); + void sendApiFailReq(Signal* signal, Uint16 aFailedNode, bool sumaOnly); void sendApiRegRef(Signal*, Uint32 ref, ApiRegRef::ErrorCode); // Generated statement blocks === modified file 'storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp' --- storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp 2009-09-01 11:42:04 +0000 +++ storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp 2009-09-03 08:56:04 +0000 @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -2741,25 +2742,55 @@ void Qmgr::checkStartInterface(Signal* s * This method is called when a DISCONNECT_REP signal arrived which means that * the API node is gone and we want to release resources in TC/DICT blocks. *---------------------------------------------------------------------------*/ -void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) +void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo, bool sumaOnly) { - NodeRecPtr failedNodePtr; - jamEntry(); - failedNodePtr.i = failedNodeNo; - signal->theData[0] = failedNodePtr.i; + signal->theData[0] = failedNodeNo; signal->theData[1] = QMGR_REF; - ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); - - failedNodePtr.p->failState = WAITING_FOR_FAILCONF1; - - /* JBB used to ensure delivery *after* any pending - * signals + /* We route the ApiFailReq signals via CMVMI + * This is done to ensure that they are received after + * any pending signals from the failed Api node when + * running ndbmtd, as these signals would be enqueued from + * the thread running CMVMI + */ + Uint32 routedSignalSectionI = RNIL; + ndbrequire(appendToSection(routedSignalSectionI, + &signal->theData[0], + 2)); + SectionHandle handle(this, routedSignalSectionI); + + /* RouteOrd data */ + RouteOrd* routeOrd = (RouteOrd*) &signal->theData[0]; + routeOrd->srcRef = reference(); + routeOrd->gsn = GSN_API_FAILREQ; + + /* Send ROUTE_ORD signals to CMVMI via JBA + * CMVMI will then immediately send the API_FAILREQ + * signals to the destination block(s) using JBB + * These API_FAILREQ signals will be sent *after* + * any JBB signals enqueued from the failed API + * by the CMVMI thread. */ - sendSignal(DBTC_REF, GSN_API_FAILREQ, signal, 2, JBB); - sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBB); - sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBB); + if (!sumaOnly) + { + routeOrd->dstRef = DBTC_REF; + sendSignalNoRelease(CMVMI_REF, GSN_ROUTE_ORD, signal, + RouteOrd::SignalLength, + JBA, &handle); + + routeOrd->dstRef = DBDICT_REF; + sendSignalNoRelease(CMVMI_REF, GSN_ROUTE_ORD, signal, + RouteOrd::SignalLength, + JBA, &handle); + } + + /* Suma always notified */ + routeOrd->dstRef = SUMA_REF; + sendSignal(CMVMI_REF, GSN_ROUTE_ORD, signal, + RouteOrd::SignalLength, + JBA, &handle); + }//Qmgr::sendApiFailReq() void Qmgr::execAPI_FAILREQ(Signal* signal) @@ -3695,7 +3726,8 @@ void Qmgr::handleApiCloseComConf(Signal* * Inform application blocks TC, DICT, SUMA etc. */ jam(); - sendApiFailReq(signal, nodeId); + sendApiFailReq(signal, nodeId, false); // !sumaOnly + failedNodePtr.p->failState = WAITING_FOR_FAILCONF1; arbitRec.code = ArbitCode::ApiFail; handleArbitApiFail(signal, nodeId); } @@ -3703,13 +3735,9 @@ void Qmgr::handleApiCloseComConf(Signal* { /** * Always inform SUMA - * JBB used to ensure delivery *after* any pending - * signals. */ jam(); - signal->theData[0] = nodeId; - signal->theData[1] = QMGR_REF; - sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBB); + sendApiFailReq(signal, nodeId, true); // sumaOnly failedNodePtr.p->failState = WAITING_FOR_FAILCONF3; }