=== modified file 'storage/ndb/include/kernel/signaldata/RouteOrd.hpp' --- storage/ndb/include/kernel/signaldata/RouteOrd.hpp 2009-05-26 18:53:34 +0000 +++ storage/ndb/include/kernel/signaldata/RouteOrd.hpp 2009-09-01 17:23:26 +0000 @@ -26,12 +26,28 @@ * Request to allocate node id */ struct RouteOrd { - STATIC_CONST( SignalLength = 4 ); + + STATIC_CONST( RoutedSignalSectionNum = 0 ); + + /* 1 destination, uses JBB */ + STATIC_CONST( BackwardsCompatSignalLength = 4 ); + + /* >= 1 destination, priority control */ + STATIC_CONST( ExtendedSignalLength = 5 ); + STATIC_CONST( MaxExtraDstRefs = 10 ); + STATIC_CONST( MaxSignalLength = + ExtendedSignalLength + MaxExtraDstRefs ); Uint32 dstRef; Uint32 srcRef; Uint32 gsn; - Uint32 cnt; + Uint32 extraDstCount; /* > 0 == count of extra DstRefs */ + + /* Following entries only understood by nodes of at least + * version NDB_MULTI_ROUTEORD_VERSION + */ + Uint32 jobBuffLevel; + Uint32 extraDstRefs[ MaxExtraDstRefs ]; }; #endif === modified file 'storage/ndb/include/ndb_version.h.in' --- storage/ndb/include/ndb_version.h.in 2009-05-27 15:21:45 +0000 +++ storage/ndb/include/ndb_version.h.in 2009-09-01 15:14:05 +0000 @@ -106,7 +106,7 @@ Uint32 ndbGetOwnVersion(); #define NDBD_MAX_RECVBYTESIZE_32K MAKE_VERSION(6,3,18) #define NDBD_LONG_SCANFRAGREQ MAKE_VERSION(6,4,0) #define NDBD_MT_LQH_VERSION MAKE_VERSION(6,4,0) - +#define NDBD_MULTI_ROUTEORD_VERSION MAKE_VERSION(7,0,8); static inline === 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-01 17:37:21 +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,102 @@ 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); + Uint32 secCount = handle.m_cnt; + ndbrequire(secCount >= 1 && secCount <= 3); + jamLine(secCount); + + RouteOrd* ord = (RouteOrd*)signal->getDataPtr(); + Uint32 dstRef = ord->dstRef; + Uint32 srcRef = ord->srcRef; + Uint32 gsn = ord->gsn; + Uint32 reqLength = signal->length(); + Uint32 extraDstCount = ord->extraDstCount; + JobBufferLevel jbLevel = JBB; + if (reqLength > RouteOrd::BackwardsCompatSignalLength) + { + jam(); + jbLevel = (JobBufferLevel) ord->jobBuffLevel; + } + + if (extraDstCount > 0) + { + jam(); + ndbrequire(reqLength == RouteOrd::ExtendedSignalLength + extraDstCount); + ndbrequire(extraDstCount <= RouteOrd::MaxExtraDstRefs); + } + + /* Put destination list on the stack */ + Uint32 destinations[ 1 + RouteOrd::MaxExtraDstRefs ]; + destinations[0] = dstRef; + memcpy(&destinations[1], &ord->extraDstRefs[0], extraDstCount << 2); + + /** + * Put section 0 in signal->theData + */ + Uint32 sigLen = handle.m_ptr[RouteOrd::RoutedSignalSectionNum].sz; + ndbrequire(sigLen <= 25); + SegmentedSectionPtr save = handle.m_ptr[RouteOrd::RoutedSignalSectionNum]; + copy(signal->theData, handle.m_ptr[RouteOrd::RoutedSignalSectionNum]); + for (Uint32 i = 0; i < secCount - 1; i++) + handle.m_ptr[i] = handle.m_ptr[i+1]; + handle.m_cnt--; + + for (Uint32 dst = 0; dst < (1 + extraDstCount); dst++) + { + jam(); + dstRef = destinations[ dst ]; + const bool lastSend = (dst == extraDstCount); + Uint32 nodeId = refToNode(dstRef); + + if (likely((nodeId == 0) || + getNodeInfo(nodeId).m_connected)) + { + jam(); + + if (!lastSend) + { + jam(); + sendSignalNoRelease(dstRef, gsn, signal, sigLen, jbLevel, &handle); + } + else + { + jam(); + sendSignal(dstRef, gsn, signal, sigLen, jbLevel, &handle); + } + } + else + { + jam(); + warningEvent("Unable to route GSN: %d from %x to %x", + gsn, srcRef, dstRef); + if (lastSend) + releaseSections(handle); + } + } + + /* All sends done, extra sections freed, free first section */ + handle.m_cnt = 1; + handle.m_ptr[0] = save; + releaseSections(handle); + return ; +} === 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-01 15:19:04 +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/dblqh/DblqhMain.cpp' --- storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2009-08-24 13:29:00 +0000 +++ storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2009-09-01 16:04:58 +0000 @@ -8122,11 +8122,11 @@ Dblqh::sendTCKEYREF(Signal* signal, Uint ord->dstRef = ref; ord->srcRef = reference(); ord->gsn = GSN_TCKEYREF; - ord->cnt = 0; + ord->extraDstCount = 0; LinearSectionPtr ptr[3]; ptr[0].p = signal->theData+25; ptr[0].sz = TcKeyRef::SignalLength; - sendSignal(routeRef, GSN_ROUTE_ORD, signal, RouteOrd::SignalLength, JBB, + sendSignal(routeRef, GSN_ROUTE_ORD, signal, RouteOrd::BackwardsCompatSignalLength, JBB, ptr, 1); } else === 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-01 17:19:07 +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-01 17:20:27 +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; + + /* ApiFailReq data */ + signal->theData[0] = failedNodeNo; signal->theData[1] = QMGR_REF; - ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); - - failedNodePtr.p->failState = WAITING_FOR_FAILCONF1; + /* 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)); + + /* RouteOrd data */ + RouteOrd* routeOrd = (RouteOrd*) &signal->theData[0]; + routeOrd->srcRef = reference(); + routeOrd->gsn = GSN_API_FAILREQ; /* JBB used to ensure delivery *after* any pending * signals */ - 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); + routeOrd->jobBuffLevel = JBB; + + if (sumaOnly) + { + routeOrd->dstRef = SUMA_REF; + routeOrd->extraDstCount = 0; + } + else + { + routeOrd->dstRef = DBTC_REF; + routeOrd->extraDstRefs[ 0 ] = DBDICT_REF; + routeOrd->extraDstRefs[ 1 ] = SUMA_REF; + routeOrd->extraDstCount = 2; + } + + SectionHandle handle(this, routedSignalSectionI); + + /* Ask CMVMI to send for us immediately (JBA) */ + sendSignal(CMVMI_REF, GSN_ROUTE_ORD, signal, + RouteOrd::ExtendedSignalLength + + routeOrd->extraDstCount, + 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); + 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 == true failedNodePtr.p->failState = WAITING_FOR_FAILCONF3; }