diff options
Diffstat (limited to 'ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp')
-rw-r--r-- | ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 2337 |
1 files changed, 798 insertions, 1539 deletions
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 4211645ace6..b5a5d0948bb 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -23,13 +23,10 @@ #include <signaldata/DictTabInfo.hpp> #include <signaldata/CreateTable.hpp> #include <signaldata/ReadNodesConf.hpp> -#include <signaldata/CntrMasterReq.hpp> -#include <signaldata/CntrMasterConf.hpp> #include <signaldata/NodeFailRep.hpp> #include <signaldata/TcKeyReq.hpp> #include <signaldata/TcKeyConf.hpp> #include <signaldata/EventReport.hpp> -#include <signaldata/SetVarReq.hpp> #include <signaldata/NodeStateSignalData.hpp> #include <signaldata/StopPerm.hpp> #include <signaldata/StopMe.hpp> @@ -39,9 +36,11 @@ #include <signaldata/AbortAll.hpp> #include <signaldata/SystemError.hpp> #include <signaldata/NdbSttor.hpp> +#include <signaldata/CntrStart.hpp> #include <signaldata/DumpStateOrd.hpp> #include <signaldata/FsRemoveReq.hpp> +#include <signaldata/ReadConfig.hpp> #include <AttributeHeader.hpp> #include <Configuration.hpp> @@ -50,8 +49,6 @@ #include <NdbOut.hpp> #include <NdbTick.h> -#define ZSYSTEM_RUN 256 - /** * ALL_BLOCKS Used during start phases and while changing node state * @@ -60,25 +57,27 @@ struct BlockInfo { BlockReference Ref; // BlockReference Uint32 NextSP; // Next start phase + Uint32 ErrorInsertStart; + Uint32 ErrorInsertStop; }; static BlockInfo ALL_BLOCKS[] = { - { DBTC_REF, 1 }, - { DBDIH_REF, 1 }, - { DBLQH_REF, 1 }, - { DBACC_REF, 1 }, - { DBTUP_REF, 1 }, - { DBDICT_REF, 1 }, - { NDBFS_REF, 0 }, - { NDBCNTR_REF, 0 }, - { QMGR_REF, 1 }, - { CMVMI_REF, 1 }, + { DBTC_REF, 1 , 8000, 8035 }, + { DBDIH_REF, 1 , 7000, 7173 }, + { DBLQH_REF, 1 , 5000, 5030 }, + { DBACC_REF, 1 , 3000, 3999 }, + { DBTUP_REF, 1 , 4000, 4007 }, + { DBDICT_REF, 1 , 6000, 6003 }, + { NDBFS_REF, 0 , 2000, 2999 }, + { NDBCNTR_REF, 0 , 1000, 1999 }, + { QMGR_REF, 1 , 1, 999 }, + { CMVMI_REF, 1 , 9000, 9999 }, { TRIX_REF, 1 }, - { BACKUP_REF, 1 }, - { DBUTIL_REF, 1 }, - { SUMA_REF, 1 }, + { BACKUP_REF, 1 , 10000, 10999 }, + { DBUTIL_REF, 1 , 11000, 11999 }, + { SUMA_REF, 1 , 13000, 13999 }, { GREP_REF, 1 }, - { DBTUX_REF, 1 } + { DBTUX_REF, 1 , 12000, 12999 } }; static const Uint32 ALL_BLOCKS_SZ = sizeof(ALL_BLOCKS)/sizeof(BlockInfo); @@ -91,33 +90,27 @@ void Ndbcntr::execCONTINUEB(Signal* signal) jamEntry(); UintR Ttemp1 = signal->theData[0]; switch (Ttemp1) { - case ZCONTINUEB_1: - jam(); - if (cwaitContinuebFlag == ZFALSE) { - jam(); -/*******************************/ -/* SIGNAL NOT WANTED ANYMORE */ -/*******************************/ - return; - } else { + case ZSTARTUP:{ + if(getNodeState().startLevel == NodeState::SL_STARTED){ jam(); -/*******************************/ -/* START ALREADY IN PROGRESS */ -/*******************************/ - if (cstartProgressFlag == ZVOTING) { - jam(); - systemErrorLab(signal); - return; - }//if - if (ctypeOfStart == NodeState::ST_NODE_RESTART) { - jam(); - systemErrorLab(signal); - return; - }//if - ph2ELab(signal); return; - }//if + } + + if(cmasterNodeId == getOwnNodeId() && c_start.m_starting.isclear()){ + jam(); + trySystemRestart(signal); + // Fall-through + } + + Uint64 now = NdbTick_CurrentMillisecond(); + if(c_start.m_startFailureTimeout > now){ + ndbrequire(false); + } + + signal->theData[0] = ZSTARTUP; + sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1); break; + } case ZSHUTDOWN: jam(); c_stopRec.checkTimeout(signal); @@ -189,28 +182,18 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal) return; }//Ndbcntr::execSYSTEM_ERROR() -/*---------------------------------------------------------------------------*/ -/* The STTOR signal is on level C, we use CONTINUEB to get into level B */ -/*---------------------------------------------------------------------------*/ -/**************************** >----------------------------------------------*/ -/* STTOR > SENDER : MISSRA */ -/**************************** >------------------+ RECEIVER : NDBCNTR */ - /* INPUT : CSTART_PHASE */ - /* CSIGNAL_KEY */ - /*---------------------------*/ -/*******************************/ -/* STTOR */ -/*******************************/ void Ndbcntr::execSTTOR(Signal* signal) { jamEntry(); cstartPhase = signal->theData[1]; - csignalKey = signal->theData[6]; NodeState newState(NodeState::SL_STARTING, cstartPhase, (NodeState::StartType)ctypeOfStart); updateNodeState(signal, newState); + cndbBlocksCount = 0; + cinternalStartphase = cstartPhase - 1; + switch (cstartPhase) { case 0: if(theConfiguration.getInitialStart()){ @@ -244,6 +227,7 @@ void Ndbcntr::execSTTOR(Signal* signal) case 6: jam(); getNodeGroup(signal); + // Fall through break; case ZSTART_PHASE_8: jam(); @@ -327,80 +311,37 @@ void Ndbcntr::execNDB_STTORRY(Signal* signal) }//switch }//Ndbcntr::execNDB_STTORRY() -/* -4.2 START PHASE 1 */ -/*###########################################################################*/ -/*LOAD OUR BLOCK REFERENCE AND OUR NODE ID. LOAD NODE IDS OF ALL NODES IN */ -/* CLUSTER CALCULATE BLOCK REFERENCES OF ALL BLOCKS IN THIS NODE */ -/*---------------------------------------------------------------------------*/ -/*******************************/ -/* STTOR */ -/*******************************/ void Ndbcntr::startPhase1Lab(Signal* signal) { jamEntry(); initData(signal); - cownBlockref = calcNdbCntrBlockRef(0); - cnoRunNodes = 0; - cnoRegNodes = 0; - - NdbBlocksRecPtr ndbBlocksPtr; cdynamicNodeId = 0; - cownBlockref = calcNdbCntrBlockRef(getOwnNodeId()); - cqmgrBlockref = calcQmgrBlockRef(getOwnNodeId()); - cdictBlockref = calcDictBlockRef(getOwnNodeId()); - cdihBlockref = calcDihBlockRef(getOwnNodeId()); - clqhBlockref = calcLqhBlockRef(getOwnNodeId()); - ctcBlockref = calcTcBlockRef(getOwnNodeId()); - ccmvmiBlockref = numberToRef(CMVMI, getOwnNodeId()); + NdbBlocksRecPtr ndbBlocksPtr; ndbBlocksPtr.i = 0; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = clqhBlockref; + ndbBlocksPtr.p->blockref = DBLQH_REF; ndbBlocksPtr.i = 1; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = cdictBlockref; + ndbBlocksPtr.p->blockref = DBDICT_REF; ndbBlocksPtr.i = 2; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = calcTupBlockRef(getOwnNodeId()); + ndbBlocksPtr.p->blockref = DBTUP_REF; ndbBlocksPtr.i = 3; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = calcAccBlockRef(getOwnNodeId()); + ndbBlocksPtr.p->blockref = DBACC_REF; ndbBlocksPtr.i = 4; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = ctcBlockref; + ndbBlocksPtr.p->blockref = DBTC_REF; ndbBlocksPtr.i = 5; ptrAss(ndbBlocksPtr, ndbBlocksRec); - ndbBlocksPtr.p->blockref = cdihBlockref; + ndbBlocksPtr.p->blockref = DBDIH_REF; sendSttorry(signal); return; } -/* -4.3 START PHASE 2 */ -/*###########################################################################*/ -// SEND A REGISTATION REQUEST TO QMGR AND WAIT FOR REPLY APPL_REGCONF OR -// APPL_REGREF COLLECT ALL OTHER NDB NODES -// AND THEIR STATES FIND OUT WHAT KIND OF START THIS NODE ARE GOING TO PERFORM -// IF THIS IS A SYSTEM OR INITIAL -// RESTART THEN FIND OUT WHO IS THE MASTER IF THIS NODE BECOME THE CNTR MASTER -// THEN COLLECT CNTR_MASTERREQ FROM -// ALL OTHER REGISTRATED CNTR THE MASTER WILL SEND BACK A CNTR_MASTERCONF WITH -// FINAL DECISSION ABOUT WHAT TYPE -// OF START AND WHICH NODES ARE APPROVED TO PARTICIPATE IN THE START IF THE -// RECEIVER OF CNTR_MASTERREQ HAVE A -// BETTER CHOICE OF MASTER THEN SEND CNTR_MASTERREF. NEW NODES ARE ALWAYS -// ALLOWED TO REGISTER, EVEN DURING -// RESTART BUT THEY WILL BE IGNORED UNTIL THE START HAVE FINISHED. -// SEND SIGNAL NDBSTTOR TO ALL BLOCKS, ACC, DICT, DIH, LQH, TC AND TUP -// SEND SIGNAL APPL_REGREQ TO QMGR IN THIS NODE AND WAIT FOR REPLY -// APPL_REGCONF OR APPL_REGREF */ -/*--------------------------------------------------------------------------*/ -/*******************************/ -/* READ_NODESREF */ -/*******************************/ void Ndbcntr::execREAD_NODESREF(Signal* signal) { jamEntry(); @@ -408,25 +349,6 @@ void Ndbcntr::execREAD_NODESREF(Signal* signal) return; }//Ndbcntr::execREAD_NODESREF() -/*******************************/ -/* APPL_REGREF */ -/*******************************/ -void Ndbcntr::execAPPL_REGREF(Signal* signal) -{ - jamEntry(); - systemErrorLab(signal); - return; -}//Ndbcntr::execAPPL_REGREF() - -/*******************************/ -/* CNTR_MASTERREF */ -/*******************************/ -void Ndbcntr::execCNTR_MASTERREF(Signal* signal) -{ - jamEntry(); - systemErrorLab(signal); - return; -}//Ndbcntr::execCNTR_MASTERREF() /*******************************/ /* NDB_STARTREF */ @@ -443,17 +365,11 @@ void Ndbcntr::execNDB_STARTREF(Signal* signal) /*******************************/ void Ndbcntr::startPhase2Lab(Signal* signal) { - cinternalStartphase = cstartPhase - 1; -/*--------------------------------------*/ -/* CASE: CSTART_PHASE = ZSTART_PHASE_2 */ -/*--------------------------------------*/ - cndbBlocksCount = 0; - cwaitContinuebFlag = ZFALSE; -/* NOT WAITING FOR SIGNAL CONTINUEB */ - - clastGci = 0; - signal->theData[0] = cownBlockref; - sendSignal(cdihBlockref, GSN_DIH_RESTARTREQ, signal, 1, JBB); + c_start.m_lastGci = 0; + c_start.m_lastGciNodeId = getOwnNodeId(); + + signal->theData[0] = reference(); + sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB); return; }//Ndbcntr::startPhase2Lab() @@ -463,8 +379,8 @@ void Ndbcntr::startPhase2Lab(Signal* signal) void Ndbcntr::execDIH_RESTARTCONF(Signal* signal) { jamEntry(); - cmasterDihId = signal->theData[0]; - clastGci = signal->theData[1]; + //cmasterDihId = signal->theData[0]; + c_start.m_lastGci = signal->theData[1]; ctypeOfStart = NodeState::ST_SYSTEM_RESTART; ph2ALab(signal); return; @@ -488,370 +404,449 @@ void Ndbcntr::ph2ALab(Signal* signal) /* from QMGR */ /* READ_NODESREQ */ /******************************/ - signal->theData[0] = cownBlockref; - sendSignal(cqmgrBlockref, GSN_READ_NODESREQ, signal, 1, JBB); + signal->theData[0] = reference(); + sendSignal(QMGR_REF, GSN_READ_NODESREQ, signal, 1, JBB); return; }//Ndbcntr::ph2ALab() +inline +Uint64 +setTimeout(Uint64 time, Uint32 timeoutValue){ + if(timeoutValue == 0) + return ~0; + return time + timeoutValue; +} + /*******************************/ /* READ_NODESCONF */ /*******************************/ void Ndbcntr::execREAD_NODESCONF(Signal* signal) { jamEntry(); - ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0]; + const ReadNodesConf * readNodes = (ReadNodesConf *)&signal->theData[0]; - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - jam(); - ptrAss(nodePtr, nodeRec); - if(NodeBitmask::get(readNodes->allNodes, nodePtr.i)){ - jam(); - nodePtr.p->nodeDefined = ZTRUE; - } else { - jam(); - nodePtr.p->nodeDefined = ZFALSE; - }//if - }//for + cmasterNodeId = readNodes->masterNodeId; + cdynamicNodeId = readNodes->ndynamicId; + + /** + * All defined nodes... + */ + c_allDefinedNodes.assign(NdbNodeBitmask::Size, readNodes->allNodes); + c_clusterNodes.assign(NdbNodeBitmask::Size, readNodes->clusterNodes); - CfgBlockRecPtr cfgBlockPtr; + Uint32 to_1 = 30000; + Uint32 to_2 = 0; + Uint32 to_3 = 0; + + const ndb_mgm_configuration_iterator * p = + theConfiguration.getOwnConfigIterator(); + + ndbrequire(p != 0); + ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT, &to_1); + ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT, &to_2); + ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3); + + c_start.m_startPartialTimeout = setTimeout(c_start.m_startTime, to_1); + c_start.m_startPartitionedTimeout = setTimeout(c_start.m_startTime, to_2); + c_start.m_startFailureTimeout = setTimeout(c_start.m_startTime, to_3); + + if(getNodeInfo(cmasterNodeId).m_version < MAKE_VERSION(3,5,0)){ + /** + * Old NDB running + */ + UpgradeStartup::sendCmAppChg(* this, signal, 0); // ADD + return; + } + + sendCntrStartReq(signal); - cfgBlockPtr.i = 0; - ptrAss(cfgBlockPtr, cfgBlockRec); - signal->theData[0] = cownBlockref; - signal->theData[1] = cfgBlockPtr.i; - sendSignal(ccmvmiBlockref, GSN_CMVMI_CFGREQ, signal, 2, JBB); return; } -/*******************************/ -/* CMVMI_CFGCONF */ -/*******************************/ -void Ndbcntr::execCMVMI_CFGCONF(Signal* signal) -{ - CfgBlockRecPtr cfgBlockPtr; +void +Ndbcntr::execCM_ADD_REP(Signal* signal){ + jamEntry(); + c_clusterNodes.set(signal->theData[0]); +} + +void +Ndbcntr::sendCntrStartReq(Signal * signal){ jamEntry(); - CmvmiCfgConf * const cfgConf = (CmvmiCfgConf *)&signal->theData[0]; + CntrStartReq * req = (CntrStartReq*)signal->getDataPtrSend(); + req->startType = ctypeOfStart; + req->lastGci = c_start.m_lastGci; + req->nodeId = getOwnNodeId(); + sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_START_REQ, + signal, CntrStartReq::SignalLength, JBB); +} - cfgBlockPtr.i = cfgConf->startPhase; - ptrCheckGuard(cfgBlockPtr, ZSIZE_CFG_BLOCK_REC, cfgBlockRec); - for(unsigned int i = 0; i<CmvmiCfgConf::NO_OF_WORDS; i++) - cfgBlockPtr.p->cfgData[i] = cfgConf->theData[i]; +void +Ndbcntr::execCNTR_START_REF(Signal * signal){ + jamEntry(); + const CntrStartRef * ref = (CntrStartRef*)signal->getDataPtr(); - if (cfgBlockPtr.i < 4) { + switch(ref->errorCode){ + case CntrStartRef::NotMaster: jam(); - cfgBlockPtr.i = cfgBlockPtr.i + 1; - signal->theData[0] = cownBlockref; - signal->theData[1] = cfgBlockPtr.i; - sendSignal(ccmvmiBlockref, GSN_CMVMI_CFGREQ, signal, 2, JBB); + cmasterNodeId = ref->masterNodeId; + sendCntrStartReq(signal); return; - } + } + ndbrequire(false); +} + +void +Ndbcntr::StartRecord::reset(){ + m_starting.clear(); + m_waiting.clear(); + m_withLog.clear(); + m_withoutLog.clear(); + m_lastGci = m_lastGciNodeId = 0; + m_startPartialTimeout = ~0; + m_startPartitionedTimeout = ~0; + m_startFailureTimeout = ~0; - jam(); + m_logNodesCount = 0; +} + +void +Ndbcntr::execCNTR_START_CONF(Signal * signal){ + jamEntry(); + const CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr(); + + cnoStartNodes = conf->noStartNodes; + ctypeOfStart = (NodeState::StartType)conf->startType; + c_start.m_lastGci = conf->startGci; + cmasterNodeId = conf->masterNodeId; + NdbNodeBitmask tmp; + tmp.assign(NdbNodeBitmask::Size, conf->startedNodes); + c_startedNodes.bitOR(tmp); + c_start.m_starting.assign(NdbNodeBitmask::Size, conf->startingNodes); + ph2GLab(signal); + + UpgradeStartup::sendCmAppChg(* this, signal, 2); //START +} + +/** + * Tried with parallell nr, but it crashed in DIH + * so I turned it off, as I don't want to debug DIH now... + * Jonas 19/11-03 + * + * After trying for 2 hours, I gave up. + * DIH is not designed to support it, and + * it requires quite of lot of changes to + * make it work + * Jonas 5/12-03 + */ +#define PARALLELL_NR 0 - cfgBlockPtr.i = 0; - ptrAss(cfgBlockPtr, cfgBlockRec); +#if PARALLELL_NR +const bool parallellNR = true; +#else +const bool parallellNR = false; +#endif + +void +Ndbcntr::execCNTR_START_REP(Signal* signal){ + jamEntry(); + Uint32 nodeId = signal->theData[0]; + c_startedNodes.set(nodeId); + c_start.m_starting.clear(nodeId); - cdelayStart = cfgBlockPtr.p->cfgData[0]; + if(!c_start.m_starting.isclear()){ + jam(); + return; + } - signal->theData[0] = cownBlockref; - signal->theData[1] = strlen(ZNAME_OF_APPL) | (ZNAME_OF_APPL[0] << 8); - signal->theData[2] = ZNAME_OF_APPL[1] | (ZNAME_OF_APPL[2] << 8); - signal->theData[9] = ZAPPL_SUBTYPE; - signal->theData[10] = 0; //NDB_VERSION; - sendSignal(cqmgrBlockref, GSN_APPL_REGREQ, signal, 11, JBB); - return; /* WAIT FOR APPL_REGCONF */ -}//Ndbcntr::execCMVMI_CFGCONF() + if(cmasterNodeId != getOwnNodeId()){ + c_start.reset(); + return; + } -/*******************************/ -/* APPL_REGCONF */ -/*******************************/ -void Ndbcntr::execAPPL_REGCONF(Signal* signal) -{ - jamEntry(); - cqmgrConnectionP = signal->theData[0]; - cnoNdbNodes = signal->theData[1]; - if(ctypeOfStart == NodeState::ST_INITIAL_START){ - cmasterCandidateId = signal->theData[2]; - } else { - cmasterCandidateId = ZNIL; + if(c_start.m_waiting.isclear()){ + c_start.reset(); + return; } - nodePtr.i = getOwnNodeId(); - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); + startWaitingNodes(signal); +} + +void +Ndbcntr::execCNTR_START_REQ(Signal * signal){ + jamEntry(); + const CntrStartReq * req = (CntrStartReq*)signal->getDataPtr(); - /*----------------------------------------------------------------------*/ - /* CALCULATE HOW MANY NODES THAT WE NEED TO PERFORM A START. MAKE A */ - /* DECISION ABOUT WAITING FOR MORE NODES OR TO CONTINUE AT ONCE */ - /*----------------------------------------------------------------------*/ - nodePtr.p->state = ZADD; - nodePtr.p->ndbVersion = 0; //NDB_VERSION; - nodePtr.p->subType = ZAPPL_SUBTYPE; - nodePtr.p->dynamicId = signal->theData[3]; - // Save dynamic nodeid in global variable - cdynamicNodeId = nodePtr.p->dynamicId; - cnoRegNodes = cnoRegNodes + 1; - switch((NodeState::StartType)ctypeOfStart){ - case NodeState::ST_INITIAL_START: + const Uint32 nodeId = req->nodeId; + const Uint32 lastGci = req->lastGci; + const NodeState::StartType st = (NodeState::StartType)req->startType; + + if(cmasterNodeId == 0){ jam(); - cnoNeedNodes = cnoNdbNodes; - break; - case NodeState::ST_SYSTEM_RESTART: - if (cnoNdbNodes == 2) { - jam(); - /*--------------------------------------*/ - /* NEED > 50% OF ALL NODES. */ - /* WE WILL SEND CONTINUEB WHEN THE WE */ - /* RECEIVE THE FIRST APPL_CHANGEREP. */ - /*--------------------------------------*/ - cnoNeedNodes = 1; /* IF ONLY 2 NODES IN CLUSTER, 1 WILL DO*/ - } else { - jam(); - cnoNeedNodes = (cnoNdbNodes >> 1) + 1; - }//if - break; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - break; - default: - ndbrequire(false); - }//if + // Has not completed READNODES yet + sendSignalWithDelay(reference(), GSN_CNTR_START_REQ, signal, 100, + signal->getLength()); + return; + } - /*--------------------------------------------------------------*/ - /* WE CAN COME HERE ALSO IN A NODE RESTART IF THE */ - /* REGISTRATION OF A RUNNING NODE HAPPENS TO ARRIVE BEFORE*/ - /* THE APPL_REGCONF SIGNAL. */ - /* IN THAT CASE CNO_NEED_NODES = ZNIL IF NOT NODE_STATE */ - /* SIGNAL HAS RETURNED THE PROPER VALUE. IN BOTH CASES WE */ - /* DO NOT NEED TO ASSIGN IT HERE. */ - /*--------------------------------------------------------------*/ - ph2CLab(signal); - return; -}//Ndbcntr::execAPPL_REGCONF() - -/*--------------------------------------------------------------*/ -/* CHECK THAT WE GOT ALL NODES REGISTRATED AS WE NEED FOR THIS */ -/* KIND OF START. WE ALWAYS END UP HERE AFTER HANDLING OF */ -/* APPL_CHANGEREP AND NODE_STATESCONF */ -/*--------------------------------------------------------------*/ -void Ndbcntr::ph2CLab(Signal* signal) -{ - NodeRecPtr ownNodePtr; - ownNodePtr.i = getOwnNodeId(); - ptrCheckGuard(ownNodePtr, MAX_NDB_NODES, nodeRec); - if (ownNodePtr.p->state != ZADD) { + if(cmasterNodeId != getOwnNodeId()){ jam(); + sendCntrStartRef(signal, nodeId, CntrStartRef::NotMaster); return; - }//if - switch (ctypeOfStart) { - case NodeState::ST_INITIAL_START: + } + + const NodeState & nodeState = getNodeState(); + switch(nodeState.startLevel){ + case NodeState::SL_NOTHING: + case NodeState::SL_CMVMI: jam(); - if (cnoRegNodes == cnoNeedNodes) { - jam(); - ph2ELab(signal); -/*******************************/ -/* ALL NODES ADDED */ -/*******************************/ - return; - }//if + ndbrequire(false); + case NodeState::SL_STARTING: + case NodeState::SL_STARTED: + break; + + case NodeState::SL_STOPPING_1: + case NodeState::SL_STOPPING_2: + case NodeState::SL_STOPPING_3: + case NodeState::SL_STOPPING_4: + jam(); + sendCntrStartRef(signal, nodeId, CntrStartRef::StopInProgress); + return; + } + + /** + * Am I starting (or started) + */ + const bool starting = (nodeState.startLevel != NodeState::SL_STARTED); + + c_start.m_waiting.set(nodeId); + switch(st){ + case NodeState::ST_INITIAL_START: + c_start.m_withoutLog.set(nodeId); break; case NodeState::ST_SYSTEM_RESTART: - ndbrequire(cnoRunNodes == 0); - if (cnoRegNodes == cnoNdbNodes) { + c_start.m_withLog.set(nodeId); + if(starting && lastGci > c_start.m_lastGci){ jam(); - /*******************************/ - /* ALL NODES ADDED */ - /*******************************/ - ph2ELab(signal); + CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend(); + ref->errorCode = CntrStartRef::NotMaster; + ref->masterNodeId = nodeId; + NodeReceiverGroup rg (NDBCNTR, c_start.m_waiting); + sendSignal(rg, GSN_CNTR_START_REF, signal, + CntrStartRef::SignalLength, JBB); return; - }//if - if (cwaitContinuebFlag == ZFALSE) { - if (cnoRegNodes == cnoNeedNodes) { - jam(); - /****************************************/ - /* ENOUGH NODES ADDED, WAIT CDELAY_START*/ - /****************************************/ - cwaitContinuebFlag = ZTRUE; - /*******************************/ - /* A DELAY SIGNAL TO MYSELF */ - /*******************************/ - signal->theData[0] = ZCONTINUEB_1; - sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, - signal, cdelayStart * 1000, 1); - return; - }//if - }//if + } + if(starting){ + Uint32 i = c_start.m_logNodesCount++; + c_start.m_logNodes[i].m_nodeId = nodeId; + c_start.m_logNodes[i].m_lastGci = req->lastGci; + } break; case NodeState::ST_NODE_RESTART: case NodeState::ST_INITIAL_NODE_RESTART: - jam(); - if (cnoNeedNodes <= cnoRunNodes) { - /*----------------------------------------------*/ - /* GOT ALL RUNNING NODES */ - /* " =< " :NODES MAY HAVE FINISHED A NODERESTART*/ - /* WHILE WE WERE WAITING FOR NODE_STATESCONF */ - /*----------------------------------------------*/ - if (cnoRegNodes != (cnoRunNodes + 1)) { - jam(); - systemErrorLab(signal); - return; - }//if - getStartNodes(signal); - cwaitContinuebFlag = ZFALSE; - cstartProgressFlag = ZTRUE; - /*--------------------------------------------------------------*/ - /* IF SOMEONE ELSE IS PERFORMING NODERESTART THEN WE GOT A REF */ - /* AND WE HAVE TO MAKE A NEW NODE_STATESREQ */ - /*--------------------------------------------------------------*/ - sendCntrMasterreq(signal); - }//if - break; - default: - jam(); - systemErrorLab(signal); - return; - break; - }//switch - /*--------------------------------------------------------------*/ - /* WAIT FOR THE CONTINUEB SIGNAL */ - /* AND / OR MORE NODES TO REGISTER */ - /*--------------------------------------------------------------*/ - return; -}//Ndbcntr::ph2CLab() + case NodeState::ST_ILLEGAL_TYPE: + ndbrequire(false); + } -/*******************************/ -/* CONTINUEB */ -/*******************************/ -/*--------------------------------------------------------------*/ -/* WE COME HERE ONLY IN SYSTEM RESTARTS AND INITIAL START. FOR */ -/* INITIAL START WE HAVE ALREADY CALCULATED THE MASTER. FOR */ -/* SYSTEM RESTART WE NEED TO PERFORM A VOTING SCHEME TO AGREE */ -/* ON A COMMON MASTER. WE GET OUR VOTE FROM DIH AND THE RESTART */ -/* INFORMATION IN DIH. */ -/*--------------------------------------------------------------*/ -void Ndbcntr::ph2ELab(Signal* signal) -{ - cwaitContinuebFlag = ZFALSE; -/*--------------------------------------*/ -/* JMP TO THIS WHEN ENOUGH NO OF */ -/* NODES ADDED */ -/*--------------------------------------*/ -/*--------------------------------------*/ -/* IGNORE CONTINUEB SIGNAL */ -/* CONTINUEB SIGNALS WILL EXIT AT */ -/* SIGNAL RECEPTION */ -/*--------------------------------------*/ - if (cnoRegNodes >= cnoNeedNodes) { + const bool startInProgress = !c_start.m_starting.isclear(); + + if((starting && startInProgress) || (startInProgress && !parallellNR)){ jam(); - getStartNodes(signal); - if (ctypeOfStart == NodeState::ST_INITIAL_START) { - if (cmasterCandidateId != getOwnNodeId()) { - jam(); -/*--------------------------------------*/ -/* THIS NODE IS NOT THE MASTER */ -/* DON'T SEND ANY MORE CNTR_MASTERREQ */ -/* VOTE FOR MASTER */ -/*--------------------------------------*/ - cstartProgressFlag = ZTRUE; - sendCntrMasterreq(signal); - resetStartVariables(signal); - } else { - jam(); - masterreq020Lab(signal); - }//if - } else if (ctypeOfStart == NodeState::ST_SYSTEM_RESTART) { - jam(); -/*--------------------------------------------------------------*/ -/* WE START THE SELECTION OF MASTER PROCESS. IF WE HAVE NOT */ -/* COMPLETED THIS BEFORE THE TIME OUT WE WILL TRY A NEW RESTART.*/ -/*--------------------------------------------------------------*/ - cwaitContinuebFlag = ZTRUE; - cstartProgressFlag = ZVOTING; - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - jam(); - ptrAss(nodePtr, nodeRec); - if (nodePtr.p->state == ZADD) { - jam(); - signal->theData[0] = getOwnNodeId(); - signal->theData[1] = cmasterDihId; - signal->theData[2] = clastGci; - sendSignal(nodePtr.p->cntrBlockref, GSN_VOTE_MASTERORD, - signal, 3, JBB); - }//if - }//for - } else { - jam(); - systemErrorLab(signal); - }//if + // We're already starting together with a bunch of nodes + // Let this node wait... + return; + } + + if(starting){ + trySystemRestart(signal); } else { - jam(); -/*--------------------------------------------------------------*/ -/* TOO FEW NODES TO START */ -/* WE HAVE WAITED FOR THE GIVEN TIME OUT AND NOT ENOUGH NODES */ -/* HAS REGISTERED. WE WILL CRASH AND RENEW THE ATTEMPT TO START */ -/* THE SYSTEM. */ -/*--------------------------------------------------------------*/ - systemErrorLab(signal); - }//if + startWaitingNodes(signal); + } + return; -}//Ndbcntr::ph2ELab() +} -/*******************************/ -/* MASTER NODE CONFIRMS REQ */ -/* CNTR_MASTERCONF */ -/*******************************/ -void Ndbcntr::execCNTR_MASTERCONF(Signal* signal) -{ +void +Ndbcntr::startWaitingNodes(Signal * signal){ + +#if ! PARALLELL_NR + const Uint32 nodeId = c_start.m_waiting.find(0); + const Uint32 Tref = calcNdbCntrBlockRef(nodeId); + ndbrequire(nodeId != c_start.m_waiting.NotFound); + + NodeState::StartType nrType = NodeState::ST_NODE_RESTART; + if(c_start.m_withoutLog.get(nodeId)){ + nrType = NodeState::ST_INITIAL_NODE_RESTART; + } + + /** + * Let node perform restart + */ + CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend(); + conf->noStartNodes = 1; + conf->startType = nrType; + conf->startGci = ~0; // Not used + conf->masterNodeId = getOwnNodeId(); + BitmaskImpl::clear(NdbNodeBitmask::Size, conf->startingNodes); + BitmaskImpl::set(NdbNodeBitmask::Size, conf->startingNodes, nodeId); + c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes); + sendSignal(Tref, GSN_CNTR_START_CONF, signal, + CntrStartConf::SignalLength, JBB); + + c_start.m_waiting.clear(nodeId); + c_start.m_withLog.clear(nodeId); + c_start.m_withoutLog.clear(nodeId); + c_start.m_starting.set(nodeId); +#else + // Parallell nr + + c_start.m_starting = c_start.m_waiting; + c_start.m_waiting.clear(); + + CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend(); + conf->noStartNodes = 1; + conf->startGci = ~0; // Not used + conf->masterNodeId = getOwnNodeId(); + c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes); + c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes); + + char buf[100]; + if(!c_start.m_withLog.isclear()){ + ndbout_c("Starting nodes w/ log: %s", c_start.m_withLog.getText(buf)); + + NodeReceiverGroup rg(NDBCNTR, c_start.m_withLog); + conf->startType = NodeState::ST_NODE_RESTART; + + sendSignal(rg, GSN_CNTR_START_CONF, signal, + CntrStartConf::SignalLength, JBB); + } + + if(!c_start.m_withoutLog.isclear()){ + ndbout_c("Starting nodes wo/ log: %s", c_start.m_withoutLog.getText(buf)); + NodeReceiverGroup rg(NDBCNTR, c_start.m_withoutLog); + conf->startType = NodeState::ST_INITIAL_NODE_RESTART; + + sendSignal(rg, GSN_CNTR_START_CONF, signal, + CntrStartConf::SignalLength, JBB); + } + + c_start.m_waiting.clear(); + c_start.m_withLog.clear(); + c_start.m_withoutLog.clear(); +#endif +} + +void +Ndbcntr::sendCntrStartRef(Signal * signal, + Uint32 nodeId, CntrStartRef::ErrorCode code){ + CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend(); + ref->errorCode = code; + ref->masterNodeId = cmasterNodeId; + sendSignal(calcNdbCntrBlockRef(nodeId), GSN_CNTR_START_REF, signal, + CntrStartRef::SignalLength, JBB); +} + +CheckNodeGroups::Output +Ndbcntr::checkNodeGroups(Signal* signal, const NdbNodeBitmask & mask){ + CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0]; + sd->blockRef = reference(); + sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck; + sd->mask = mask; + EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal, + CheckNodeGroups::SignalLength); jamEntry(); + return (CheckNodeGroups::Output)sd->output; +} - CntrMasterConf * const cntrMasterConf = - (CntrMasterConf *)&signal->theData[0]; +bool +Ndbcntr::trySystemRestart(Signal* signal){ + /** + * System restart something + */ + const bool allNodes = c_start.m_waiting.equal(c_allDefinedNodes); + const bool allClusterNodes = c_start.m_waiting.equal(c_clusterNodes); + const Uint64 now = NdbTick_CurrentMillisecond(); - cnoStartNodes = cntrMasterConf->noStartNodes; - int index = 0; - unsigned i; - for (i = 1; i < MAX_NDB_NODES; i++) { + if(!allClusterNodes){ jam(); - if (NodeBitmask::get(cntrMasterConf->theNodes, i)) { - jam(); - cstartNodes[index] = i; - index++; - }//if - }//for - if (cnoStartNodes != index) { + return false; + } + + if(!allNodes && c_start.m_startPartialTimeout > now){ jam(); - systemErrorLab(signal); - }//if - ph2FLab(signal); - return; -}//Ndbcntr::execCNTR_MASTERCONF() + return false; + } -void Ndbcntr::ph2FLab(Signal* signal) -{ -/*--------------------------------------------------------------*/ -//The nodes have been selected and we now know which nodes are -// included in the system restart. We can reset wait for CONTINUEB -// flag to ensure system is not restarted when CONTINUEB after the -// delay. -/*--------------------------------------------------------------*/ - cmasterNodeId = cmasterCandidateId; - cwaitContinuebFlag = ZFALSE; - ph2GLab(signal); - return; -}//Ndbcntr::ph2FLab() + NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART; + if(c_start.m_waiting.equal(c_start.m_withoutLog)){ + if(!allNodes){ + jam(); + return false; + } + srType = NodeState::ST_INITIAL_START; + c_start.m_starting = c_start.m_withoutLog; // Used for starting... + c_start.m_withoutLog.clear(); + } else { + + CheckNodeGroups::Output wLog = checkNodeGroups(signal, c_start.m_withLog); + + switch (wLog) { + case CheckNodeGroups::Win: + jam(); + break; + case CheckNodeGroups::Lose: + jam(); + // If we lose with all nodes, then we're in trouble + ndbrequire(!allNodes); + return false; + break; + case CheckNodeGroups::Partitioning: + jam(); + bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0); + + if(allNodes){ + jam(); + if(allowPartition){ + jam(); + break; + } + ndbrequire(false); // All nodes -> partitioning, which is not allowed + } + + if(c_start.m_startPartitionedTimeout > now){ + jam(); + return false; + } + break; + } + + // For now only with the "logged"-ones. + // Let the others do node restart afterwards... + c_start.m_starting = c_start.m_withLog; + c_start.m_withLog.clear(); + } + + /** + * Okidoki, we try to start + */ + CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr(); + conf->noStartNodes = c_start.m_starting.count(); + conf->startType = srType; + conf->startGci = c_start.m_lastGci; + conf->masterNodeId = c_start.m_lastGciNodeId; + c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes); + c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes); + + ndbrequire(c_start.m_lastGciNodeId == getOwnNodeId()); + + NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); + sendSignal(rg, GSN_CNTR_START_CONF, signal, CntrStartConf::SignalLength,JBB); + + c_start.m_waiting.bitANDC(c_start.m_starting); + + return true; +} -/*--------------------------------------*/ -/* RECEIVED CNTR_MASTERCONF */ -/*--------------------------------------*/ -/*******************************/ -/* NDB_STTORRY */ -/*******************************/ -/*---------------------------------------------------------------------------*/ -// NOW WE CAN START NDB START PHASE 1. IN THIS PHASE ALL BLOCKS -// (EXCEPT DIH THAT INITIALISED WHEN -// RECEIVING DIH_RESTARTREQ) WILL INITIALISE THEIR DATA, COMMON VARIABLES, -// LINKED LISTS AND RECORD VARIABLES. -/*---------------------------------------------------------------------------*/ void Ndbcntr::ph2GLab(Signal* signal) { if (cndbBlocksCount < ZNO_NDB_BLOCKS) { @@ -879,11 +874,6 @@ void Ndbcntr::ph2GLab(Signal* signal) /*******************************/ void Ndbcntr::startPhase3Lab(Signal* signal) { - cinternalStartphase = cstartPhase - 1; -/*--------------------------------------*/ -/* CASE: CSTART_PHASE = ZSTART_PHASE_3 */ -/*--------------------------------------*/ - cndbBlocksCount = 0; ph3ALab(signal); return; }//Ndbcntr::startPhase3Lab() @@ -893,29 +883,12 @@ void Ndbcntr::startPhase3Lab(Signal* signal) /*******************************/ void Ndbcntr::ph3ALab(Signal* signal) { - Uint16 tnoStartNodes; - if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if -/*******************************/ -/*< APPL_STARTREG <*/ -/*******************************/ - if (ctypeOfStart == NodeState::ST_NODE_RESTART) { - jam(); - tnoStartNodes = 1; - } else if (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART) { - jam(); - tnoStartNodes = 1; - } else { - jam(); - tnoStartNodes = cnoStartNodes; - }//if - signal->theData[0] = cqmgrConnectionP; - signal->theData[1] = tnoStartNodes; - sendSignal(cqmgrBlockref, GSN_APPL_STARTREG, signal, 2, JBB); + sendSttorry(signal); return; }//Ndbcntr::ph3ALab() @@ -933,49 +906,12 @@ void Ndbcntr::ph3ALab(Signal* signal) /*******************************/ void Ndbcntr::startPhase4Lab(Signal* signal) { - cinternalStartphase = cstartPhase - 1; -/*--------------------------------------*/ -/* CASE: CSTART_PHASE = ZSTART_PHASE_4 */ -/*--------------------------------------*/ - cndbBlocksCount = 0; - cnoWaitrep = 0; - if (capplStartconfFlag != ZTRUE) { - jam(); -/*------------------------------------------------------*/ -/* HAVE WE ALREADY RECEIVED APPL_STARTCONF */ -/*------------------------------------------------------*/ - return; - }//if ph4ALab(signal); - return; }//Ndbcntr::startPhase4Lab() -/*******************************/ -/* APPL_STARTCONF */ -/*******************************/ -void Ndbcntr::execAPPL_STARTCONF(Signal* signal) -{ - jamEntry(); - if (cstartPhase == ZSTART_PHASE_4) { - jam(); - ph4ALab(signal); - return; - } else { - jam(); - capplStartconfFlag = ZTRUE; -//------------------------------------------------ -/* FLAG WILL BE CHECKED WHEN WE RECEIVED STTOR */ -/* SIGNAL MAY BE RECEIVED IN STARTPHASE 3 */ -//------------------------------------------------ - return; - }//if -}//Ndbcntr::execAPPL_STARTCONF() void Ndbcntr::ph4ALab(Signal* signal) { - nodePtr.i = getOwnNodeId(); - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - nodePtr.p->state = ZSTART; ph4BLab(signal); return; }//Ndbcntr::ph4ALab() @@ -1014,6 +950,7 @@ void Ndbcntr::waitpoint41Lab(Signal* signal) cnoWaitrep++; if (cnoWaitrep == cnoStartNodes) { jam(); + cnoWaitrep = 0; /*---------------------------------------------------------------------------*/ // NDB_STARTREQ STARTS UP ALL SET UP OF DISTRIBUTION INFORMATION IN DIH AND // DICT. AFTER SETTING UP THIS @@ -1025,9 +962,9 @@ void Ndbcntr::waitpoint41Lab(Signal* signal) // 3) EXECUTING THE FRAGMENT REDO LOG FROM ONE OR SEVERAL NODES TO // RESTORE THE RESTART CONFIGURATION OF DATA IN NDB CLUSTER. /*---------------------------------------------------------------------------*/ - signal->theData[0] = cownBlockref; + signal->theData[0] = reference(); signal->theData[1] = ctypeOfStart; - sendSignal(cdihBlockref, GSN_NDB_STARTREQ, signal, 2, JBB); + sendSignal(DBDIH_REF, GSN_NDB_STARTREQ, signal, 2, JBB); }//if } else { jam(); @@ -1037,11 +974,10 @@ void Ndbcntr::waitpoint41Lab(Signal* signal) /* SLAVES WONT DO ANYTHING UNTIL THEY */ /* RECEIVE A WAIT REPORT FROM THE MASTER*/ /*--------------------------------------*/ - nodePtr.i = cmasterNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); signal->theData[0] = getOwnNodeId(); signal->theData[1] = ZWAITPOINT_4_1; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); + sendSignal(calcNdbCntrBlockRef(cmasterNodeId), + GSN_CNTR_WAITREP, signal, 2, JBB); }//if return; }//Ndbcntr::waitpoint41Lab() @@ -1052,23 +988,11 @@ void Ndbcntr::waitpoint41Lab(Signal* signal) void Ndbcntr::execNDB_STARTCONF(Signal* signal) { jamEntry(); - UintR guard0; - UintR Ttemp1; - guard0 = cnoStartNodes - 1; - arrGuard(guard0, MAX_NDB_NODES); - for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) { - jam(); - if (cstartNodes[Ttemp1] != getOwnNodeId()) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = getOwnNodeId(); - signal->theData[1] = ZWAITPOINT_4_2; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); - }//if - }//for - sendSttorry(signal); + NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = ZWAITPOINT_4_2; + sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); return; }//Ndbcntr::execNDB_STARTCONF() @@ -1084,9 +1008,6 @@ void Ndbcntr::execNDB_STARTCONF(Signal* signal) /*******************************/ void Ndbcntr::startPhase5Lab(Signal* signal) { - cinternalStartphase = cstartPhase - 1; - cndbBlocksCount = 0; - cnoWaitrep = 0; ph5ALab(signal); return; }//Ndbcntr::startPhase5Lab() @@ -1147,16 +1068,17 @@ void Ndbcntr::ph5ALab(Signal* signal) // SEND NDB START PHASE 5 IN NODE RESTARTS TO COPY DATA TO THE NEWLY // STARTED NODE. /*----------------------------------------------------------------------*/ - req->senderRef = cownBlockref; + req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = ctypeOfStart; req->masterNodeId = cmasterNodeId; + //#define TRACE_STTOR #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase); #endif - sendSignal(cdihBlockref, GSN_NDB_STTOR, signal, + sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal, NdbSttor::SignalLength, JBB); return; case NodeState::ST_INITIAL_START: @@ -1170,11 +1092,10 @@ void Ndbcntr::ph5ALab(Signal* signal) /* RECEIVE A WAIT REPORT FROM THE MASTER*/ /* WHEN THE MASTER HAS FINISHED HIS WORK*/ /*--------------------------------------*/ - nodePtr.i = cmasterNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); signal->theData[0] = getOwnNodeId(); signal->theData[1] = ZWAITPOINT_5_2; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); + sendSignal(calcNdbCntrBlockRef(cmasterNodeId), + GSN_CNTR_WAITREP, signal, 2, JBB); return; default: ndbrequire(false); @@ -1198,8 +1119,10 @@ void Ndbcntr::waitpoint52Lab(Signal* signal) /*--------------------------------------*/ if (cnoWaitrep == cnoStartNodes) { jam(); + cnoWaitrep = 0; + NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend(); - req->senderRef = cownBlockref; + req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = ctypeOfStart; @@ -1207,7 +1130,7 @@ void Ndbcntr::waitpoint52Lab(Signal* signal) #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase); #endif - sendSignal(cdihBlockref, GSN_NDB_STTOR, signal, + sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal, NdbSttor::SignalLength, JBB); }//if return; @@ -1218,28 +1141,19 @@ void Ndbcntr::waitpoint52Lab(Signal* signal) /*******************************/ void Ndbcntr::ph6ALab(Signal* signal) { - UintR guard0; - UintR Ttemp1; - if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); waitpoint51Lab(signal); return; }//if - guard0 = cnoStartNodes - 1; - arrGuard(guard0, MAX_NDB_NODES); - for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) { - jam(); - if (cstartNodes[Ttemp1] != getOwnNodeId()) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = getOwnNodeId(); - signal->theData[1] = ZWAITPOINT_5_1; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); - }//if - }//for + + NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); + rg.m_nodes.clear(getOwnNodeId()); + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = ZWAITPOINT_5_1; + sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); + waitpoint51Lab(signal); return; }//Ndbcntr::ph6ALab() @@ -1283,28 +1197,18 @@ void Ndbcntr::waitpoint61Lab(Signal* signal) cnoWaitrep6++; if (cnoWaitrep6 == cnoStartNodes) { jam(); - Uint32 guard0 = cnoStartNodes - 1; - arrGuard(guard0, MAX_NDB_NODES); - for (Uint32 Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) { - jam(); - if (cstartNodes[Ttemp1] != getOwnNodeId()) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = getOwnNodeId(); - signal->theData[1] = ZWAITPOINT_6_2; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); - } - } + NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); + rg.m_nodes.clear(getOwnNodeId()); + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = ZWAITPOINT_6_2; + sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); sendSttorry(signal); } } else { jam(); - nodePtr.i = cmasterNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); signal->theData[0] = getOwnNodeId(); signal->theData[1] = ZWAITPOINT_6_1; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); + sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); } } @@ -1339,28 +1243,18 @@ void Ndbcntr::waitpoint71Lab(Signal* signal) cnoWaitrep7++; if (cnoWaitrep7 == cnoStartNodes) { jam(); - Uint32 guard0 = cnoStartNodes - 1; - arrGuard(guard0, MAX_NDB_NODES); - for (Uint32 Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) { - jam(); - if (cstartNodes[Ttemp1] != getOwnNodeId()) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = getOwnNodeId(); - signal->theData[1] = ZWAITPOINT_7_2; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); - } - } + NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); + rg.m_nodes.clear(getOwnNodeId()); + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = ZWAITPOINT_7_2; + sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); sendSttorry(signal); } } else { jam(); - nodePtr.i = cmasterNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); signal->theData[0] = getOwnNodeId(); signal->theData[1] = ZWAITPOINT_7_1; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB); + sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); } } @@ -1378,315 +1272,11 @@ void Ndbcntr::ph8ALab(Signal* signal) // NODES WHICH PERFORM A NODE RESTART NEEDS TO GET THE DYNAMIC ID'S // OF THE OTHER NODES HERE. /*---------------------------------------------------------------------------*/ - signal->theData[0] = cqmgrConnectionP; - sendSignal(cqmgrBlockref, GSN_APPL_RUN, signal, 1, JBB); - nodePtr.i = getOwnNodeId(); - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - nodePtr.p->state = ZRUN; - cnoRunNodes = cnoRunNodes + 1; sendSttorry(signal); - cstartProgressFlag = ZFALSE; - ctypeOfStart = (NodeState::StartType)ZSYSTEM_RUN; resetStartVariables(signal); return; }//Ndbcntr::ph8BLab() -/* -4.7 HANDLE GLOBAL EVENTS, NOT BOUNDED TO INITIALSTART OR SYSTEM RESTART */ -/*#######################################################################*/ -/*******************************/ -/* APPL_CHANGEREP */ -/*******************************/ -void Ndbcntr::execAPPL_CHANGEREP(Signal* signal) -{ - jamEntry(); - Uint16 TapplEvent = signal->theData[0]; - Uint16 TapplVersion = signal->theData[1]; - Uint16 TapplNodeId = signal->theData[2]; - Uint16 TapplSubType = signal->theData[3]; - - nodePtr.i = TapplNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - nodePtr.p->subType = TapplSubType; - nodePtr.p->ndbVersion = TapplVersion; - nodePtr.p->dynamicId = signal->theData[4]; - - switch (TapplEvent) { - case ZADD: -/*----------------------------*/ -/* ADD A NEW NDB NODE TO FILE */ -/*----------------------------*/ - if (nodePtr.p->state == ZREMOVE) { - jam(); - if (cnoRegNodes == cnoNdbNodes) { - jam(); -/*----------------------------------------------*/ -/* DON'T ACCEPT MORE NODES THAN SYSFILE.CFG SPEC*/ -/*----------------------------------------------*/ - systemErrorLab(signal); - return; - }//if - nodePtr.p->state = ZADD; - cnoRegNodes = cnoRegNodes + 1; - } else { - jam(); - systemErrorLab(signal); - return; - }//if - if (cstartProgressFlag == ZFALSE) { -/*----------------------------------------------*/ -/* FLAG = TRUE WHEN CNTR_MASTERREQ IS SENT */ -/*----------------------------------------------*/ - switch (ctypeOfStart) { - case NodeState::ST_INITIAL_START: - case NodeState::ST_SYSTEM_RESTART: - jam(); - ph2CLab(signal); -/*----------------------------------------------*/ -/* CHECK IF READY TO MAKE A CNTR_MASTERREQ */ -/*----------------------------------------------*/ - break; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - jam(); -/*------------------------------------------------------------------------*/ -/* THIS SHOULD NEVER OCCUR SINCE WE HAVE ALREADY BEEN ALLOWED TO */ -/* START OUR NODE. THE NEXT NODE CANNOT START UNTIL WE ARE FINISHED */ -/*------------------------------------------------------------------------*/ - systemErrorLab(signal); - break; - case ZSYSTEM_RUN: - jam(); - /*empty*/; - break; - default: - jam(); -/*------------------------------------------------------------------------*/ -/* NO PARTICULAR ACTION IS NEEDED. THE NODE WILL PERFORM A NODE */ -/* RESTART BUT NO ACTION IS NEEDED AT THIS STAGE IN THE RESTART. */ -/*------------------------------------------------------------------------*/ - systemErrorLab(signal); - break; - }//switch - } else { - jam(); -/*--------------------------------------------------------------------------*/ -// WHEN A RESTART IS IN PROGRESS THERE IS A POSSIBILITY THAT A NODE -// REGISTER AND -// THINKS THAT HE WOULD BE THE MASTER (LOWER NODE ID) BUT THE OTHER NODE IS -// ALREADY RUNNING THE RESTART. THIS WILL BE DETECTED WHEN HE ATTEMPTS A -// CNTR_MASTERREQ AND RECEIVES A REFUSE SIGNAL IN RETURN. THIS WILL CAUSE HIM -// TO CRASH. IF HE ATTEMPTS TO JOIN AS A NON-MASTER HE WILL WAIT FOR THE MASTER. -// IN THIS CASE IT IS BETTER TO SHOT HIM DOWN. FOR SAFETY REASONS WE WILL ALWAYS -// SHOT HIM DOWN. -/*--------------------------------------------------------------------------*/ - const BlockReference tblockref = calcNdbCntrBlockRef(nodePtr.i); - - SystemError * const sysErr = (SystemError*)&signal->theData[0]; - sysErr->errorCode = SystemError::StartInProgressError; - sysErr->errorRef = reference(); - sendSignal(tblockref, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA); - }//if - break; - case ZSTART: - jam(); - if (nodePtr.p->state != ZADD) { - jam(); - systemErrorLab(signal); - return; - }//if - nodePtr.p->state = ZSTART; - break; - case ZRUN: - if (nodePtr.p->state == ZREMOVE) { - jam(); - cnoRegNodes = cnoRegNodes + 1; - } else { - jam(); - if (nodePtr.p->state != ZSTART) { - jam(); -/*----------------------------------------------*/ -/* STATE ZADD OR ZRUN -> ZRUN NOT ALLOWED */ -/*----------------------------------------------*/ - systemErrorLab(signal); - return; - }//if - }//if - cnoRunNodes = cnoRunNodes + 1; - nodePtr.p->state = ZRUN; - switch (ctypeOfStart) { - case NodeState::ST_INITIAL_START: - jam(); - detectNoderestart(signal); - if (ctypeOfStart == NodeState::ST_NODE_RESTART) { - jam(); -/*--------------------------------------------------------------------------*/ -/* WE DISCOVERED THAT WE ARE TRYING TO PERFORM A INITIAL START WHEN THERE */ -/* ARE ALREADY RUNNING NODES. THIS MEANS THAT THE NODE HAS CLEANED THE */ -/* FILE SYSTEM AND CONTAINS NO DATA. THIS IS AN INITIAL NODE RESTART WHICH */ -/* IS NECESSARY TO START A NODE THAT HAS BEEN TAKEN OVER. */ -/*--------------------------------------------------------------------------*/ - ctypeOfStart = NodeState::ST_INITIAL_NODE_RESTART; - }//if - break; - case NodeState::ST_SYSTEM_RESTART: - jam(); - detectNoderestart(signal); -/*----------------------------------------------*/ -/* SHOULD THIS NODE PERFORM A NODE RESTART? */ -/* THEN CHANGE CTYPE_OF_START TO NodeState::ST_NODE_RESTART */ -/* AND SEND NODE_STATESREQ. */ -/* WAIT FOR NODE_STATESCONF. */ -/*----------------------------------------------*/ - break; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - jam(); -/*----------------------------------------------*/ -/* IF WE ARE WAITING FOR NODE_STATESCONF, THIS */ -/* JUMP WILL EXIT BECAUSE CNO_NEED_NODES = ZNIL */ -/* UNTIL WE RECEIVE NODE_STATESCONF */ -/*----------------------------------------------*/ - ph2CLab(signal); - break; - case ZSYSTEM_RUN: - jam(); - break; - default: - jam(); - systemErrorLab(signal); - break; - }//switch - break; - default: - jam(); - systemErrorLab(signal); - break; - }//switch - return; -}//Ndbcntr::execAPPL_CHANGEREP() - -/*--------------------------------------------------------------------------*/ -// A NODE HAS ADDED HAS VOTE ON WHICH MASTER IS TO BE CHOOSEN IN A SYSTEM -// RESTART. WHEN ALL VOTES HAVE -// BEEN ADDED THEN WE ARE PREPARED TO CHOOSE MASTER AND CONTINUE WITH THE -// RESTART PROCESSING. -/*--------------------------------------------------------------------------*/ - -/*******************************/ -/* VOT_MASTERORD */ -/*******************************/ -void Ndbcntr::execVOTE_MASTERORD(Signal* signal) -{ - jamEntry(); - nodePtr.i = signal->theData[0]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - UintR TmasterCandidateId = signal->theData[1]; - UintR TlastGci = signal->theData[2]; - if (ctypeOfStart != NodeState::ST_SYSTEM_RESTART) { - jam(); - progError(__LINE__, - ERR_SR_RESTARTCONFLICT, - "One ore more nodes probably requested an initial SR"); - return; - }//if - cmasterVoters = cmasterVoters + 1; - if (cmasterVoters == 1) { - jam(); - cmasterCurrentId = TmasterCandidateId; - cmasterLastGci = TlastGci; - } else { - if (cmasterLastGci < TlastGci) { - jam(); - cmasterCurrentId = TmasterCandidateId; - cmasterLastGci = TlastGci; - } else if (cmasterLastGci == TlastGci) { - jam(); - if (cmasterCurrentId != TmasterCandidateId) { - jam(); - systemErrorLab(signal); - return; - }//if - }//if - }//if - if (cstartProgressFlag == ZVOTING) { -/*--------------------------------------------------------------------------*/ -// UNLESS START PROGRESS FLAG IS SET TO VOTING WE HAVE NOT YET REACHED A -// STATE WHERE WE ARE READY TO -// PROCEED WITH THE SYSTEM RESTART. OUR OWN NOTE HAVE AT LEAST NOT BEEN -// CAST INTO THE BALLOT YET. -/*--------------------------------------------------------------------------*/ - if (cmasterVoters == cnoRegNodes) { - cmasterCandidateId = cmasterCurrentId; - if (cmasterCandidateId == getOwnNodeId()) { - jam(); - masterreq020Lab(signal); - return; - } else { - jam(); - cstartProgressFlag = ZTRUE; - sendCntrMasterreq(signal); - resetStartVariables(signal); - }//if - }//if - }//if - return; -}//Ndbcntr::execVOTE_MASTERORD() - -/*******************************/ -/* CNTR_MASTERREQ */ -/*******************************/ -void Ndbcntr::execCNTR_MASTERREQ(Signal* signal) -{ - Uint16 ttypeOfStart; - - jamEntry(); - - CntrMasterReq * const cntrMasterReq = - (CntrMasterReq *)&signal->theData[0]; - -//----------------------------------------------- -// cntrMasterReq->userBlockRef NOT USED -//----------------------------------------------- - Uint16 TuserNodeId = cntrMasterReq->userNodeId; - ttypeOfStart = cntrMasterReq->typeOfStart; - Uint16 TnoRestartNodes = cntrMasterReq->noRestartNodes; - int index = 0; - unsigned i; - for (i = 1; i < MAX_NDB_NODES; i++) { - jam(); - if (NodeBitmask::get(cntrMasterReq->theNodes, i)) { - jam(); - cstartNodes[index] = i; - index++; - }//if - }//for - if (TnoRestartNodes != index) { - jam(); - systemErrorLab(signal); - }//if - switch (ttypeOfStart) { - case NodeState::ST_INITIAL_START: - case NodeState::ST_SYSTEM_RESTART: - jam(); -//-------------------------------- -/* ELECTION OF MASTER AT */ -/* INITIAL OR SYSTEM RESTART */ -//-------------------------------- - masterreq010Lab(signal, TnoRestartNodes, TuserNodeId); - break; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - jam(); - masterreq030Lab(signal, TnoRestartNodes, TuserNodeId); - break; - default: - jam(); - systemErrorLab(signal); - break; - }//switch -}//Ndbcntr::execCNTR_MASTERREQ() - /*******************************/ /* CNTR_WAITREP */ /*******************************/ @@ -1736,243 +1326,102 @@ void Ndbcntr::execCNTR_WAITREP(Signal* signal) }//switch }//Ndbcntr::execCNTR_WAITREP() -/* -4.7.4 MASTERREQ_010 ( CASE: INITIALSTART OR SYSTEMRESTART ) */ -/*--------------------------------------------------------------------------*/ -// ELECTION OF MASTER AND ELECTION OF PARTICIPANTS IN START. SENDER OF -// CNTR_MASTERREQ THINKS THAT THIS NODE -// SHOULD BE THE MASTER. WE CAN'T MAKE A DECISION ABOUT WHO THE MASTER -// SHOULD BE UNTIL TIMELIMIT HAS EXPIRED AND -// THAT AT LEAST CNO_NEED_NODES ARE ZADD IN NODE_PTR_REC. IF THIS NODE IS -// MASTER THEN MAKE SURE THAT ALL NODES IN -// THE CLUSTER COMES TO AN AGREEMENT ABOUT A SUBSET OF NODES THAT SATISFIES -// THE NUMBER CNO_NEED_NODES. THERE IS -// A POSSIBILITY THAT THE RECEIVER OF CNTR_MASTERREQ DOESN'T HAS CHOOSEN -// A MASTER, THEN THE RECEIVER CAN'T -// EITHER CONFIRM OR REFUSE JUST STORE THE VOTES OF THE CLUSTERMEMBERS. -// IF THIS NODE BECOME AWARE OF THAT ANOTHER NODE IS MASTER THEN CHECK IF -// ANYONE HAS VOTED (SENT CNTR_MASTERREQ) */ -// AND THEN SEND THEM CNTR_MASTERREF BACK. -/*--------------------------------------------------------------------------*/ -void Ndbcntr::masterreq010Lab(Signal* signal, - Uint16 TnoRestartNodes, - Uint16 TuserNodeId) -{ - UintR guard0; - UintR Ttemp1; - - nodePtr.i = TuserNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - if (cstartProgressFlag == ZTRUE) { - jam(); -/*--------------------------------------*/ -/* RESTART ALREADY IN PROGRESS */ -/*--------------------------------------*/ - if (ctypeOfStart == NodeState::ST_INITIAL_START) { - jam(); - systemErrorLab(signal); - return; - }//if - signal->theData[0] = cownBlockref; - signal->theData[1] = getOwnNodeId(); - signal->theData[2] = ZSTART_IN_PROGRESS_ERROR; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB); - return; - }//if - cnoVoters = cnoVoters + 1; - nodePtr.p->voter = ZTRUE; - guard0 = TnoRestartNodes - 1; - arrGuard(guard0, MAX_NDB_NODES); - for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - nodePtr.p->votes = nodePtr.p->votes + 1; - }//for - masterreq020Lab(signal); - return; -}//Ndbcntr::masterreq010Lab() - -/*----------------------------------------------------------------------*/ -/* WHEN WE JUST WANT TO CHECK OUR VOTES IT IS POSSIBLE TO JUMP TO THIS */ -/* LABEL. IF WE HAVEN'T RECEIVED ANY VOTES SINCE OUR LASTCHECK WE WILL */ -/* JUST PERFORM AN EXIT */ -/*----------------------------------------------------------------------*/ -void Ndbcntr::masterreq020Lab(Signal* signal) -{ - if (cmasterCandidateId == ZNIL) { - jam(); -/*--------------------------------------*/ -/* MASTER UNKNOWN */ -/*--------------------------------------*/ - return; - } else if (cmasterCandidateId == getOwnNodeId()) { - jam(); -/*--------------------------------------*/ -/* SATISFIED WHEN WE HAVE AS MANY VOTERS*/ -/* AS RESTARTNODES - 1, DIFFERENT NODES?*/ -/* <- CNO_START_NODES, ALL NODES AGREED */ -/* ON THESE CNO_START_NODES */ -/*--------------------------------------*/ - if ((cnoStartNodes - 1) == cnoVoters) { - chooseRestartNodes(signal); - if (cnoStartNodes >= cnoNeedNodes) { - jam(); - cstartProgressFlag = ZTRUE; -/*--------------------------------------*/ -/* DON'T SEND ANY MORE CNTR_MASTERREQ */ -/*--------------------------------------*/ - replyMasterconfToAll(signal); -/*--------------------------------------*/ -/* SEND CONF TO ALL PASSED REQ */ -/* DON'T SEND ANYTHING TO REJECTED NODES*/ -/* BLOCK THEM UNTIL SYSTEM IS RUNNING */ -/* CONTINUE RESTART */ -/*--------------------------------------*/ - ph2FLab(signal); - } else { - jam(); - systemErrorLab(signal); - }//if - }//if - } else { - jam(); -/*----------------------------------------------------------------------*/ -/* WE RECEIVED A REQUEST TO A MASTER WHILE NOT BEING MASTER. THIS */ -/* MUST BE AN ERROR INDICATION. WE CRASH. */ -/*----------------------------------------------------------------------*/ - systemErrorLab(signal); - }//if - return; /* WAIT FOR MORE CNTR_MASTERREQ */ -}//Ndbcntr::masterreq020Lab() - -void Ndbcntr::masterreq030Lab(Signal* signal, - Uint16 TnoRestartNodes, - Uint16 TuserNodeId) -{ - UintR TretCode; - if (cmasterNodeId == getOwnNodeId()) { - jam(); - TretCode = checkNodelist(signal, TnoRestartNodes); - nodePtr.i = TuserNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - if (TretCode == 1) { - jam(); -/*******************************************************<*/ -/* CSTART_NODES IS OVERWRITTEN IN RECEIVING BLOCK, */ -/* SO WE MUST SEND CNTR_MASTERCONF TO THE SAME */ -/* CSTART_NODES AS WE RECEIVED IN CNTR_MASTERREQ */ -/*******************************************************<*/ - - CntrMasterConf * const cntrMasterConf = - (CntrMasterConf *)&signal->theData[0]; - NodeBitmask::clear(cntrMasterConf->theNodes); - for (int i = 0; i < TnoRestartNodes; i++){ - jam(); - UintR Tnode = cstartNodes[i]; - arrGuard(Tnode, MAX_NDB_NODES); - NodeBitmask::set(cntrMasterConf->theNodes, Tnode); - }//for - cntrMasterConf->noStartNodes = TnoRestartNodes; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERCONF, - signal, CntrMasterConf::SignalLength, JBB); - } else { - jam(); - signal->theData[0] = cownBlockref; - signal->theData[1] = getOwnNodeId(); - signal->theData[2] = ZTOO_FEW_NODES; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB); - }//if - } else { - jam(); - nodePtr.i = TuserNodeId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = cownBlockref; - signal->theData[1] = getOwnNodeId(); - signal->theData[2] = ZNOT_MASTER; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB); - }//if - return; -}//Ndbcntr::masterreq030Lab() - /*******************************/ /* NODE_FAILREP */ /*******************************/ void Ndbcntr::execNODE_FAILREP(Signal* signal) { - UintR TfailureNr; - UintR TnoOfNodes; - UintR TreadNodes[MAX_NDB_NODES]; - jamEntry(); + const NodeFailRep * nodeFail = (NodeFailRep *)&signal->theData[0]; + NdbNodeBitmask allFailed; + allFailed.assign(NdbNodeBitmask::Size, nodeFail->theNodes); + + NdbNodeBitmask failedStarted = c_startedNodes; + NdbNodeBitmask failedStarting = c_start.m_starting; + NdbNodeBitmask failedWaiting = c_start.m_waiting; + + failedStarted.bitAND(allFailed); + failedStarting.bitAND(allFailed); + failedWaiting.bitAND(allFailed); + + const bool tMasterFailed = allFailed.get(cmasterNodeId); + const bool tStarted = !failedStarted.isclear(); + const bool tStarting = !failedStarting.isclear(); + const bool tWaiting = !failedWaiting.isclear(); + + if(tMasterFailed){ + jam(); + /** + * If master has failed choose qmgr president as master + */ + cmasterNodeId = nodeFail->masterNodeId; + } + + /** + * Clear node bitmasks from failed nodes + */ + c_start.m_starting.bitANDC(allFailed); + c_start.m_waiting.bitANDC(allFailed); + c_start.m_withLog.bitANDC(allFailed); + c_start.m_withoutLog.bitANDC(allFailed); + c_clusterNodes.bitANDC(allFailed); + c_startedNodes.bitANDC(allFailed); + const NodeState & st = getNodeState(); if(st.startLevel == st.SL_STARTING){ - if(!st.getNodeRestartInProgress()){ + jam(); + + const Uint32 phase = st.starting.startPhase; + + const bool tStartConf = (phase > 2) || (phase == 2 && cndbBlocksCount > 0); + + if(tMasterFailed){ progError(__LINE__, ERR_SR_OTHERNODEFAILED, - "Unhandled node failure during system restart"); + "Unhandled node failure during restart"); + } + + if(tStartConf && tStarting){ + // One of other starting nodes has crashed... + progError(__LINE__, + ERR_SR_OTHERNODEFAILED, + "Unhandled node failure of starting node during restart"); } - } - - { - NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0]; - TfailureNr = nodeFail->failNo; - TnoOfNodes = nodeFail->noOfNodes; - unsigned index = 0; - unsigned i; - for (i = 0; i < MAX_NDB_NODES; i++) { - jam(); - if (NodeBitmask::get(nodeFail->theNodes, i)) { - jam(); - TreadNodes[index] = i; - index++; - ndbrequire(getOwnNodeId() != i); - }//if + if(tStartConf && tStarted){ + // One of other started nodes has crashed... + progError(__LINE__, + ERR_SR_OTHERNODEFAILED, + "Unhandled node failure of started node during restart"); + } + + Uint32 nodeId = 0; + while(!allFailed.isclear()){ + nodeId = allFailed.find(nodeId + 1); + allFailed.clear(nodeId); + signal->theData[0] = nodeId; + sendSignal(QMGR_REF, GSN_NDB_FAILCONF, signal, 1, JBB); }//for - ndbrequire(TnoOfNodes == index); + + return; } - for (Uint32 i = 0; i < TnoOfNodes; i++) { - jam(); - nodePtr.i = TreadNodes[i]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - signal->theData[0] = EventReport::NODE_FAILREP; - signal->theData[1] = nodePtr.i; - signal->theData[2] = nodePtr.p->state; - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); - if (nodePtr.p->state != ZREMOVE) { - jam(); - deleteNode(signal); - }//if - }//for + ndbrequire(!allFailed.get(getOwnNodeId())); -/*******************************/ -/*< NODE_FAILREP <*/ -/*******************************/ - NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0]; - - nodeFail->failNo = TfailureNr; - nodeFail->masterNodeId = cmasterNodeId; + NodeFailRep * rep = (NodeFailRep *)&signal->theData[0]; + rep->masterNodeId = cmasterNodeId; - nodeFail->noOfNodes = TnoOfNodes; - NodeBitmask::clear(nodeFail->theNodes); - for (unsigned i = 0; i < TnoOfNodes; i++) { - jam(); - NodeBitmask::set(nodeFail->theNodes, TreadNodes[i]); - }//for - - sendSignal(ctcBlockref, GSN_NODE_FAILREP, signal, + sendSignal(DBTC_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - sendSignal(clqhBlockref, GSN_NODE_FAILREP, signal, + sendSignal(DBLQH_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - sendSignal(cdihBlockref, GSN_NODE_FAILREP, signal, + sendSignal(DBDIH_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - sendSignal(cdictBlockref, GSN_NODE_FAILREP, signal, + sendSignal(DBDICT_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal, @@ -1983,80 +1432,25 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal) sendSignal(GREP_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - return; -}//Ndbcntr::execNODE_FAILREP() -/*******************************/ -/* NODE_STATESCONF */ -/*******************************/ -void Ndbcntr::execNODE_STATESCONF(Signal* signal) -{ - jamEntry(); - cmasterCandidateId = signal->theData[0]; - cnoNeedNodes = signal->theData[1]; -/*----------------------------------------------------------------------*/ -// Now that we have knowledge of how many nodes are needed we will call -// ph2CLab to ensure that node restart continues if we already received -// all APPL_CHANGEREP signals. -/*----------------------------------------------------------------------*/ - ph2CLab(signal); - return; -}//Ndbcntr::execNODE_STATESCONF() - -/*******************************/ -/* NODE_STATESREF */ -/*******************************/ -void Ndbcntr::execNODE_STATESREF(Signal* signal) -{ - jamEntry(); - systemErrorLab(signal); - return; -}//Ndbcntr::execNODE_STATESREF() + Uint32 nodeId = 0; + while(!allFailed.isclear()){ + nodeId = allFailed.find(nodeId + 1); + allFailed.clear(nodeId); + signal->theData[0] = EventReport::NODE_FAILREP; + signal->theData[1] = nodeId; + signal->theData[2] = 0; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); + }//for -/*******************************/ -/* NODE_STATESREQ */ -/*******************************/ -void Ndbcntr::execNODE_STATESREQ(Signal* signal) -{ - UintR TnoNeedNodes = 0; - NodeRecPtr TNodePtr; - jamEntry(); - BlockReference TuserBlockref = signal->theData[0]; -/*----------------------------------------------------------------------*/ -// IF WE ARE RUNNING, WE WILL ANSWER THIS SIGNAL WITH THE AMOUNT OF NODES -// THAT ARE IN THE RUN STATE OR START STATE. -/*----------------------------------------------------------------------*/ - TNodePtr.i = getOwnNodeId(); - ptrCheckGuard(TNodePtr, MAX_NDB_NODES, nodeRec); - if (TNodePtr.p->state == ZRUN) { - jam(); - for (TNodePtr.i = 1; TNodePtr.i < MAX_NDB_NODES; TNodePtr.i++) { - jam(); - ptrAss(TNodePtr, nodeRec); - if ((TNodePtr.p->state == ZRUN) || - (TNodePtr.p->state == ZSTART)) { - jam(); - TnoNeedNodes++; - }//if - }//for - signal->theData[0] = cmasterNodeId; - signal->theData[1] = TnoNeedNodes; - sendSignal(TuserBlockref, GSN_NODE_STATESCONF, signal, 2, JBB); - } else { - jam(); - signal->theData[0] = ZERROR_NOT_RUNNING; - sendSignal(TuserBlockref, GSN_NODE_STATESREF, signal, 1, JBB); - }//if return; -}//Ndbcntr::execNODE_STATESREQ() +}//Ndbcntr::execNODE_FAILREP() /*******************************/ /* READ_NODESREQ */ /*******************************/ void Ndbcntr::execREAD_NODESREQ(Signal* signal) { - UintR TnoNodes = 0; - NodeRecPtr TNodePtr; jamEntry(); /*----------------------------------------------------------------------*/ @@ -2067,59 +1461,36 @@ void Ndbcntr::execREAD_NODESREQ(Signal* signal) BlockReference TuserBlockref = signal->theData[0]; ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0]; - if (cstartPhase > ZSTART_PHASE_2) { - ndbrequire(cstartProgressFlag == ZTRUE); - - NodeBitmask::clear(readNodes->allNodes); - NodeBitmask::clear(readNodes->inactiveNodes); - - /** - * Add started nodes - */ - for (int i = 0; i < cnoStartNodes; i++){ - jam(); - TNodePtr.i = cstartNodes[i]; - ptrCheckGuard(TNodePtr, MAX_NDB_NODES, nodeRec); - - NodeBitmask::set(readNodes->allNodes, TNodePtr.i); - readNodes->setVersionId(TNodePtr.i, TNodePtr.p->ndbVersion, - readNodes->theVersionIds); - TnoNodes++; - }//for - - /** - * Sometimes add myself - */ - if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || - (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { - jam(); - - NodeBitmask::set(readNodes->allNodes, getOwnNodeId()); - readNodes->setVersionId(getOwnNodeId(), NDB_VERSION, - readNodes->theVersionIds); - TnoNodes++; - }//if - /** - * Check all nodes which are defined but not already added - */ - for (TNodePtr.i = 1; TNodePtr.i < MAX_NDB_NODES; TNodePtr.i++) { - jam(); - ptrAss(TNodePtr, nodeRec); - if ((TNodePtr.p->nodeDefined == ZTRUE) && - (NodeBitmask::get(readNodes->allNodes, TNodePtr.i) == false)){ - jam(); + /** + * Prepare inactiveNodes bitmask. + * The concept as such is by the way pretty useless. + * It makes parallell starts more or less impossible... + */ + NdbNodeBitmask tmp1; + tmp1.bitOR(c_startedNodes); + if(!getNodeState().getNodeRestartInProgress()){ + tmp1.bitOR(c_start.m_starting); + } else { + tmp1.set(getOwnNodeId()); + } - NodeBitmask::set(readNodes->allNodes, TNodePtr.i); - NodeBitmask::set(readNodes->inactiveNodes, TNodePtr.i); - readNodes->setVersionId(TNodePtr.i, NDB_VERSION, - readNodes->theVersionIds); - - TnoNodes++; - }//if - }//for - - readNodes->noOfNodes = TnoNodes; - readNodes->masterNodeId = cmasterNodeId; + NdbNodeBitmask tmp2; + tmp2.bitOR(c_allDefinedNodes); + tmp2.bitANDC(tmp1); + /** + * Fill in return signal + */ + tmp2.copyto(NdbNodeBitmask::Size, readNodes->inactiveNodes); + c_allDefinedNodes.copyto(NdbNodeBitmask::Size, readNodes->allNodes); + c_clusterNodes.copyto(NdbNodeBitmask::Size, readNodes->clusterNodes); + c_startedNodes.copyto(NdbNodeBitmask::Size, readNodes->startedNodes); + c_start.m_starting.copyto(NdbNodeBitmask::Size, readNodes->startingNodes); + + readNodes->noOfNodes = c_allDefinedNodes.count(); + readNodes->masterNodeId = cmasterNodeId; + readNodes->ndynamicId = cdynamicNodeId; + if (cstartPhase > ZSTART_PHASE_2) { + jam(); sendSignal(TuserBlockref, GSN_READ_NODESCONF, signal, ReadNodesConf::SignalLength, JBB); @@ -2237,8 +1608,8 @@ void Ndbcntr::startInsertTransactions(Signal* signal) ckey = 1; ctransidPhase = ZTRUE; - signal->theData[1] = cownBlockref; - sendSignal(ctcBlockref, GSN_TCSEIZEREQ, signal, 2, JBB); + signal->theData[1] = reference(); + sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB); return; }//Ndbcntr::startInsertTransactions() @@ -2312,7 +1683,7 @@ void Ndbcntr::crSystab7Lab(Signal* signal) AttributeHeader::init(&tAIDataPtr[2], 1, 2); tAIDataPtr[3] = (tkey << 16); tAIDataPtr[4] = 1; - sendSignal(ctcBlockref, GSN_TCKEYREQ, signal, + sendSignal(DBTC_REF, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength + 6, JBB); }//for ckey = ckey + RowsPerCommit; @@ -2335,7 +1706,7 @@ void Ndbcntr::execTCKEYCONF(Signal* signal) Uint32 transId2 = keyConf->transId2; signal->theData[0] = transId1; signal->theData[1] = transId2; - sendSignal(ctcBlockref, GSN_TC_COMMIT_ACK, signal, 2, JBB); + sendSignal(DBTC_REF, GSN_TC_COMMIT_ACK, signal, 2, JBB); }//if cresponses = cresponses + TcKeyConf::getNoOfOperations(confInfo); @@ -2363,8 +1734,8 @@ void Ndbcntr::crSystab8Lab(Signal* signal) return; }//if signal->theData[0] = ctcConnectionP; - signal->theData[1] = cownBlockref; - sendSignal(ctcBlockref, GSN_TCRELEASEREQ, signal, 2, JBB); + signal->theData[1] = reference(); + sendSignal(DBTC_REF, GSN_TCRELEASEREQ, signal, 2, JBB); return; }//Ndbcntr::crSystab8Lab() @@ -2380,8 +1751,8 @@ void Ndbcntr::execTCRELEASECONF(Signal* signal) void Ndbcntr::crSystab9Lab(Signal* signal) { - signal->theData[1] = cownBlockref; - sendSignalWithDelay(cdihBlockref, GSN_GETGCIREQ, signal, 100, 2); + signal->theData[1] = reference(); + sendSignalWithDelay(DBDIH_REF, GSN_GETGCIREQ, signal, 100, 2); return; }//Ndbcntr::crSystab9Lab() @@ -2435,309 +1806,28 @@ void Ndbcntr::execTCSEIZEREF(Signal* signal) return; }//Ndbcntr::execTCSEIZEREF() -/* -4.10 SUBROUTINES */ -/*##########################################################################*/ -/* -4.10.1 CHECK_NODELIST */ -/*---------------------------------------------------------------------------*/ -/*CHECK THAT ALL THE NEW NODE HAS DETECTED ALL RUNNING NODES */ -/*INPUT: CSTART_NODES */ -/* TNO_RESTART_NODES */ -/* TUSER_NODE_ID */ -/*RET: CNODE_RESTART */ -/*---------------------------------------------------------------------------*/ -UintR Ndbcntr::checkNodelist(Signal* signal, Uint16 TnoRestartNodes) -{ - UintR guard1; - UintR Ttemp1; - - if (cnoRunNodes == TnoRestartNodes) { - jam(); - guard1 = TnoRestartNodes - 1; - arrGuard(guard1, MAX_NDB_NODES); - for (Ttemp1 = 0; Ttemp1 <= guard1; Ttemp1++) { - jam(); - nodePtr.i = cstartNodes[Ttemp1]; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); - if (nodePtr.p->state != ZRUN) { - jam(); - return 0; - }//if - }//for - return 1; - }//if - return 0; -}//Ndbcntr::checkNodelist() - -/*---------------------------------------------------------------------------*/ -// SELECT NODES THAT ARE IN THE STATE TO PERFORM A INITIALSTART OR -// SYSTEMRESTART. -// THIS SUBROUTINE CAN ONLY BE INVOKED BY THE MASTER NODE. -// TO BE CHOOSEN A NODE NEED AS MANY VOTES AS THERE ARE VOTERS, AND OF -// COURSE THE NODE HAS TO BE KNOWN BY THE -// MASTER -// INPUT: NODE_REC -// CNO_NEED_NODES -// RETURN:CNO_START_NODES -// CSTART_NODES -/*---------------------------------------------------------------------------*/ -void Ndbcntr::chooseRestartNodes(Signal* signal) -{ - cnoStartNodes = 0; - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - ptrAss(nodePtr, nodeRec); - if (nodePtr.p->votes == cnoVoters) { - jam(); - if (nodePtr.p->state == ZADD) { - jam(); - arrGuard(cnoStartNodes, MAX_NDB_NODES); - cstartNodes[cnoStartNodes] = nodePtr.i; - cnoStartNodes++; - }//if - } else { - jam(); - if (nodePtr.p->votes > 0) { - jam(); - systemErrorLab(signal); - return; - }//if - }//if - }//for -}//Ndbcntr::chooseRestartNodes() - -/* -4.10.6 DELETE_NODE */ -/*---------------------------------------------------------------------------*/ -// INPUT: NODE_PTR -/*---------------------------------------------------------------------------*/ -void Ndbcntr::deleteNode(Signal* signal) -{ - UintR tminDynamicId; - - if (nodePtr.p->state == ZRUN) { - jam(); - cnoRunNodes = cnoRunNodes - 1; - }//if - nodePtr.p->state = ZREMOVE; - nodePtr.p->votes = 0; - nodePtr.p->voter = ZFALSE; - cnoRegNodes--; - if (nodePtr.i == cmasterNodeId) { - jam(); - cmasterNodeId = ZNIL; -/*---------------------------------------------------------------------------*/ -// IF MASTER HAVE CRASHED WE NEED TO SELECT A NEW MASTER. -/*---------------------------------------------------------------------------*/ - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - jam(); - ptrAss(nodePtr, nodeRec); - if (nodePtr.p->state == ZRUN) { - if (cmasterNodeId == ZNIL) { - jam(); - cmasterNodeId = nodePtr.i; - tminDynamicId = nodePtr.p->dynamicId; - } else { - jam(); - if (nodePtr.p->dynamicId < tminDynamicId) { - jam(); - cmasterNodeId = nodePtr.i; - tminDynamicId = nodePtr.p->dynamicId; - }//if - }//if - }//if - }//for - }//if -}//Ndbcntr::deleteNode() - -/*---------------------------------------------------------------------------*/ -// A NEW NODE TRIES TO DETECT A NODE RESTART. NodeState::ST_NODE_RESTART IS A POSSIBLE -// STATE ONLY WHEN THE SYSTEM IS RUNNING. -// IF THE SYSTEM IS RUNNING THEN -// CTYPE_OF_START = NodeState::ST_SYSTEM_RESTART UNTIL THE FIRST NODE HAS REGISTERED. -// IF SYSTEM IS */ -// RUNNING THE FIRST NODE TO REGISTER WILL BE ZRUN AND CTYPE_OF_START -// WILL BE CHANGED */ -// TO NodeState::ST_NODE_RESTART AT PH_2C. WHEN A NodeState::ST_NODE_RESTART IS DETECTED THE NEW NODE -// HAS TO SEND */ -// A CNTR_MASTERREQ TO THE MASTER -/*---------------------------------------------------------------------------*/ -void Ndbcntr::detectNoderestart(Signal* signal) -{ - NodeRecPtr ownNodePtr; - ownNodePtr.i = getOwnNodeId(); - ptrCheckGuard(ownNodePtr, MAX_NDB_NODES, nodeRec); - if (ownNodePtr.p->state != ZADD) { - if (ownNodePtr.p->state != ZREMOVE) { - jam(); - return; - }//if - }//if - ctypeOfStart = NodeState::ST_NODE_RESTART; -/*----------------------------------------------*/ -/* THIS NODE WILL PERFORM A NODE RESTART */ -/* REQUEST OF ALL NODES STATES IN SYSTEM */ -// The purpose of this signal is to ensure that -// the starting node knows when it has received -// all APPL_CHANGEREP signals and thus can continue -// to the next step of the node restart. Thus we -// need to know the amount of nodes that are in the -// RUN state and in the START state (more than one -// node can be copying data simultaneously in the -// cluster. -/*----------------------------------------------*/ - signal->theData[0] = cownBlockref; - sendSignal(nodePtr.p->cntrBlockref, GSN_NODE_STATESREQ, signal, 1, JBB); - cnoNeedNodes = ZNIL; -/*---------------------------------*/ -/* PREVENT TO SEND NODE_STATESREQ */ -/*---------------------------------------------------------------------------*/ -/* WE NEED TO WATCH THE NODE RESTART WITH A TIME OUT TO NOT WAIT FOR EVER. */ -/*---------------------------------------------------------------------------*/ - cwaitContinuebFlag = ZTRUE; - signal->theData[0] = ZCONTINUEB_1; - sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 3 * 1000, 1); -}//Ndbcntr::detectNoderestart() - -/*---------------------------------------------------------------------------*/ -// SCAN NODE_REC FOR APPROPRIATE NODES FOR A START. -// SYSTEMRESTART AND INITALSTART DEMANDS NODES OF STATE ZADD. -// NODERESTART DEMANDS NODE OF THE STATE ZRUN. -// INPUT: CTYPE_OF_START, NODE_REC -// RETURN: CSTART_NODES(), CNO_START_NODES, CMASTER_CANDIDATE_ID -// (SYSTEMRESTART AND INITALSTART) -/*---------------------------------------------------------------------------*/ -void Ndbcntr::getStartNodes(Signal* signal) -{ - UintR Ttemp1; - if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || - (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { - jam(); - Ttemp1 = ZRUN; - } else { - jam(); -/*---------------------------------*/ -/* SYSTEM RESTART AND INITIAL START*/ -/*---------------------------------*/ - Ttemp1 = ZADD; - }//if - cnoStartNodes = 0; - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - jam(); - ptrAss(nodePtr, nodeRec); - if (nodePtr.p->state == Ttemp1) { - jam(); - cstartNodes[cnoStartNodes] = nodePtr.i;/*OVERWRITTEN AT CNTR_MASTERCONF*/ - cnoStartNodes++; - }//if - }//for -}//Ndbcntr::getStartNodes() /*---------------------------------------------------------------------------*/ /*INITIALIZE VARIABLES AND RECORDS */ /*---------------------------------------------------------------------------*/ void Ndbcntr::initData(Signal* signal) { - cmasterNodeId = ZNIL; - cmasterCandidateId = ZNIL; - cmasterVoters = 0; - cstartProgressFlag = ZFALSE; - capplStartconfFlag = ZFALSE; - cnoVoters = 0; + c_start.reset(); + cmasterNodeId = 0; cnoStartNodes = 0; - for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - ptrAss(nodePtr, nodeRec); - nodePtr.p->cntrBlockref = calcNdbCntrBlockRef(nodePtr.i); - nodePtr.p->state = ZREMOVE; - nodePtr.p->dynamicId = 0; - nodePtr.p->votes = 0; /* USED BY MASTER */ - nodePtr.p->voter = ZFALSE; /* USED BY MASTER */ - nodePtr.p->masterReq = ZFALSE; /* USED BY MASTER */ - }//for + cnoWaitrep = 0; }//Ndbcntr::initData() -/*---------------------------------------------------------------------------*/ -// THE MASTER NODE HAS CHOOSEN THE NODES WHO WERE QUALIFIED TO -// PARTICIPATE IN A INITIALSTART OR SYSTEMRESTART. -// THIS SUBROTINE SENDS A CNTR_MASTERCONF TO THESE NODES -/*---------------------------------------------------------------------------*/ -void Ndbcntr::replyMasterconfToAll(Signal* signal) -{ - if (cnoStartNodes > 1) { - /** - * Construct a MasterConf signal - */ - - CntrMasterConf * const cntrMasterConf = - (CntrMasterConf *)&signal->theData[0]; - NodeBitmask::clear(cntrMasterConf->theNodes); - - cntrMasterConf->noStartNodes = cnoStartNodes; - - for(int i = 0; i<cnoStartNodes; i++) - NodeBitmask::set(cntrMasterConf->theNodes, cstartNodes[i]); - - /** - * Then distribute it to everyone but myself - */ - for(int i = 0; i<cnoStartNodes; i++){ - const NodeId nodeId = cstartNodes[i]; - if(nodeId != getOwnNodeId()){ - sendSignal(numberToRef(number(), nodeId), - GSN_CNTR_MASTERCONF, - signal, CntrMasterConf::SignalLength, JBB); - } - } - } -}//Ndbcntr::replyMasterconfToAll() /*---------------------------------------------------------------------------*/ /*RESET VARIABLES USED DURING THE START */ /*---------------------------------------------------------------------------*/ void Ndbcntr::resetStartVariables(Signal* signal) { - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { - ptrAss(nodePtr, nodeRec); - nodePtr.p->votes = 0; - nodePtr.p->voter = ZFALSE; - nodePtr.p->masterReq = ZFALSE; - }//for - cnoVoters = 0; cnoStartNodes = 0; cnoWaitrep6 = cnoWaitrep7 = 0; }//Ndbcntr::resetStartVariables() -/*---------------------------------------------------------------------------*/ -// SENDER OF THIS SIGNAL HAS CHOOSEN A MASTER NODE AND SENDS A REQUEST -// TO THE MASTER_CANDIDATE AS AN VOTE FOR -// THE MASTER. THE SIGNAL ALSO INCLUDES VOTES FOR NODES WHICH SENDER -// THINKS SHOULD PARTICIPATE IN THE START. -// INPUT: CNO_START_NODES -// CSTART_NODES -/*---------------------------------------------------------------------------*/ -void Ndbcntr::sendCntrMasterreq(Signal* signal) -{ - nodePtr.i = cmasterCandidateId; - ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); -/*--------------------------------------------------------------*/ -/* O:INITIALSTART, 1:SYSTEMRESTART (ELECTION OF MASTER) */ -/* 2:NODE RESTART (SENDER NODE NOT INCLUDED IN CSTART_NODES) */ -/*--------------------------------------------------------------*/ - CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0]; - NodeBitmask::clear(cntrMasterReq->theNodes); - for (int i = 0; i < cnoStartNodes; i++){ - jam(); - UintR Tnode = cstartNodes[i]; - arrGuard(Tnode, MAX_NDB_NODES); - NodeBitmask::set(cntrMasterReq->theNodes, Tnode); - }//for - cntrMasterReq->userBlockRef = cownBlockref; - cntrMasterReq->userNodeId = getOwnNodeId(); - cntrMasterReq->typeOfStart = ctypeOfStart; - cntrMasterReq->noRestartNodes = cnoStartNodes; - sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREQ, - signal, CntrMasterReq::SignalLength, JBB); -}//Ndbcntr::sendCntrMasterreq() /*---------------------------------------------------------------------------*/ // SEND THE SIGNAL @@ -2745,25 +1835,24 @@ void Ndbcntr::sendCntrMasterreq(Signal* signal) /*---------------------------------------------------------------------------*/ void Ndbcntr::sendNdbSttor(Signal* signal) { - CfgBlockRecPtr cfgBlockPtr; NdbBlocksRecPtr ndbBlocksPtr; ndbBlocksPtr.i = cndbBlocksCount; ptrCheckGuard(ndbBlocksPtr, ZSIZE_NDB_BLOCKS_REC, ndbBlocksRec); - cfgBlockPtr.i = cinternalStartphase; - ptrCheckGuard(cfgBlockPtr, ZSIZE_CFG_BLOCK_REC, cfgBlockRec); + NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend(); - req->senderRef = cownBlockref; + req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = ctypeOfStart; req->masterNodeId = cmasterNodeId; for (int i = 0; i < 16; i++) { - req->config[i] = cfgBlockPtr.p->cfgData[i]; + // Garbage + req->config[i] = 0x88776655; + //cfgBlockPtr.p->cfgData[i]; } - //#define TRACE_STTOR //#define MAX_STARTPHASE 2 #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to %s", @@ -2779,9 +1868,6 @@ void Ndbcntr::sendNdbSttor(Signal* signal) /*---------------------------------------------------------------------------*/ void Ndbcntr::sendSttorry(Signal* signal) { - signal->theData[0] = csignalKey; - signal->theData[1] = 3; - signal->theData[2] = 2; signal->theData[3] = ZSTART_PHASE_1; signal->theData[4] = ZSTART_PHASE_2; signal->theData[5] = ZSTART_PHASE_3; @@ -2801,9 +1887,8 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal) DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0]; if(signal->theData[0] == 13){ infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d", - cstartPhase, cinternalStartphase, cndbBlocksCount); - infoEvent("Cntr: cmasterNodeId = %d, cmasterCandidateId = %d", - cmasterNodeId, cmasterCandidateId); + cstartPhase, cinternalStartphase, cndbBlocksCount); + infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId); } if (dumpState->args[0] == DumpStateOrd::NdbcntrTestStopOnError){ @@ -2823,6 +1908,7 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal) }//Ndbcntr::execDUMP_STATE_ORD() void Ndbcntr::execSET_VAR_REQ(Signal* signal) { +#if 0 SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0]; ConfigParamId var = setVarReq->variable(); @@ -2835,6 +1921,7 @@ void Ndbcntr::execSET_VAR_REQ(Signal* signal) { default: sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB); }// switch +#endif }//Ndbcntr::execSET_VAR_REQ() void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{ @@ -2947,7 +2034,7 @@ Ndbcntr::execSTOP_REQ(Signal* signal){ } updateNodeState(signal, newState); signal->theData[0] = ZSHUTDOWN; - sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1); + sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } void @@ -2991,14 +2078,9 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ /** * Check if I can survive me stopping */ - NodeBitmask ndbMask; ndbMask.clear(); - NodeRecPtr aPtr; - for(aPtr.i = 1; aPtr.i < MAX_NDB_NODES; aPtr.i++){ - ptrAss(aPtr, cntr.nodeRec); - if(aPtr.i != cntr.getOwnNodeId() && aPtr.p->state == ZRUN){ - ndbMask.set(aPtr.i); - } - } + NodeBitmask ndbMask; + ndbMask.assign(cntr.c_startedNodes); + ndbMask.clear(cntr.getOwnNodeId()); CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0]; sd->blockRef = cntr.reference(); @@ -3194,7 +2276,7 @@ void Ndbcntr::execSTOP_ME_CONF(Signal* signal){ c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); signal->theData[0] = ZSHUTDOWN; - sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1); + sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } void @@ -3255,6 +2337,11 @@ void Ndbcntr::execSTTORRY(Signal* signal){ c_missra.execSTTORRY(signal); } +void Ndbcntr::execREAD_CONFIG_CONF(Signal* signal){ + jamEntry(); + c_missra.execREAD_CONFIG_CONF(signal); +} + void Ndbcntr::execSTART_ORD(Signal* signal){ jamEntry(); ndbrequire(NO_OF_BLOCKS == ALL_BLOCKS_SZ); @@ -3299,7 +2386,38 @@ void Ndbcntr::Missra::execSTART_ORD(Signal* signal){ signal->theData[0] = EventReport::NDBStartStarted; signal->theData[1] = NDB_VERSION; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); + + currentBlockIndex = 0; + sendNextREAD_CONFIG_REQ(signal); +} + +void Ndbcntr::Missra::sendNextREAD_CONFIG_REQ(Signal* signal){ + + if(currentBlockIndex < ALL_BLOCKS_SZ){ + jam(); + + ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtrSend(); + req->senderData = 0; + req->senderRef = cntr.reference(); + req->noOfParameters = 0; + + const BlockReference ref = ALL_BLOCKS[currentBlockIndex].Ref; + +#if 0 + ndbout_c("sending READ_CONFIG_REQ to %s(ref=%x index=%d)", + getBlockName( refToBlock(ref)), + ref, + currentBlockIndex); +#endif + + cntr.sendSignal(ref, GSN_READ_CONFIG_REQ, signal, + ReadConfigReq::SignalLength, JBB); + return; + } + /** + * Finished... + */ currentStartPhase = 0; for(Uint32 i = 0; i<NO_OF_BLOCKS; i++){ if(ALL_BLOCKS[i].NextSP < currentStartPhase) @@ -3307,10 +2425,19 @@ void Ndbcntr::Missra::execSTART_ORD(Signal* signal){ } currentBlockIndex = 0; - sendNextSTTOR(signal); } +void Ndbcntr::Missra::execREAD_CONFIG_CONF(Signal* signal){ + const ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtr(); + + const Uint32 ref = conf->senderRef; + ndbrequire(refToBlock(ALL_BLOCKS[currentBlockIndex].Ref) == refToBlock(ref)); + + currentBlockIndex++; + sendNextREAD_CONFIG_REQ(signal); +} + void Ndbcntr::Missra::execSTTORRY(Signal* signal){ const BlockReference ref = signal->senderBlockRef(); ndbrequire(refToBlock(ref) == refToBlock(ALL_BLOCKS[currentBlockIndex].Ref)); @@ -3365,8 +2492,8 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){ currentBlockIndex); #endif - cntr.sendSignal(ref, GSN_STTOR, - signal, 8, JBB); + cntr.sendSignal(ref, GSN_STTOR, signal, 8, JBB); + return; } } @@ -3391,4 +2518,136 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){ NodeState newState(NodeState::SL_STARTED); cntr.updateNodeState(signal, newState); + + /** + * Backward + */ + UpgradeStartup::sendCmAppChg(cntr, signal, 3); //RUN + + NdbNodeBitmask nodes = cntr.c_clusterNodes; + Uint32 node = 0; + while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){ + if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){ + nodes.clear(node); + } + } + + NodeReceiverGroup rg(NDBCNTR, nodes); + signal->theData[0] = cntr.getOwnNodeId(); + cntr.sendSignal(rg, GSN_CNTR_START_REP, signal, 1, JBB); +} + +/** + * Backward compatible code + */ +void +UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){ + + signal->theData[0] = startLevel; + signal->theData[1] = cntr.getOwnNodeId(); + signal->theData[2] = 3 | ('N' << 8); + signal->theData[3] = 'D' | ('B' << 8); + signal->theData[4] = 0; + signal->theData[5] = 0; + signal->theData[6] = 0; + signal->theData[7] = 0; + signal->theData[8] = 0; + signal->theData[9] = 0; + signal->theData[10] = 0; + signal->theData[11] = 0; + + NdbNodeBitmask nodes = cntr.c_clusterNodes; + nodes.clear(cntr.getOwnNodeId()); + Uint32 node = 0; + while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){ + if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){ + cntr.sendSignal(cntr.calcQmgrBlockRef(node), + GSN_CM_APPCHG, signal, 12, JBB); + } else { + cntr.c_startedNodes.set(node); // Fake started + } + } +} + +void +UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){ + Uint32 state = signal->theData[0]; + Uint32 nodeId = signal->theData[1]; + if(block.number() == QMGR){ + Ndbcntr& cntr = * (Ndbcntr*)globalData.getBlock(CNTR); + switch(state){ + case 0: // ZADD + break; + case 2: // ZSTART + break; + case 3: // ZRUN{ + cntr.c_startedNodes.set(nodeId); + + Uint32 recv = cntr.c_startedNodes.count(); + Uint32 cnt = cntr.c_clusterNodes.count(); + if(recv + 1 == cnt){ //+1 == own node + /** + * Check master + */ + sendCntrMasterReq(cntr, signal, 0); + } + return; + } + } + block.progError(0,0); +} + +void +UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){ + Uint32 node = cntr.c_startedNodes.find(n); + if(node != NdbNodeBitmask::NotFound && + (node == cntr.getOwnNodeId() || + cntr.getNodeInfo(node).m_version >= MAKE_VERSION(3,5,0))){ + node = cntr.c_startedNodes.find(node+1); + } + + if(node == NdbNodeBitmask::NotFound){ + cntr.progError(0,0); + } + + CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0]; + cntr.c_clusterNodes.copyto(NdbNodeBitmask::Size, cntrMasterReq->theNodes); + NdbNodeBitmask::clear(cntrMasterReq->theNodes, cntr.getOwnNodeId()); + cntrMasterReq->userBlockRef = 0; + cntrMasterReq->userNodeId = cntr.getOwnNodeId(); + cntrMasterReq->typeOfStart = NodeState::ST_INITIAL_NODE_RESTART; + cntrMasterReq->noRestartNodes = cntr.c_clusterNodes.count() - 1; + cntr.sendSignal(cntr.calcNdbCntrBlockRef(node), GSN_CNTR_MASTERREQ, + signal, CntrMasterReq::SignalLength, JBB); +} + +void +UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){ + Uint32 gsn = signal->header.theVerId_signalNumber; + Uint32 node = refToNode(signal->getSendersBlockRef()); + if(block.number() == CNTR){ + Ndbcntr& cntr = (Ndbcntr&)block; + switch(gsn){ + case GSN_CNTR_MASTERREF: + sendCntrMasterReq(cntr, signal, node + 1); + return; + break; + case GSN_CNTR_MASTERCONF:{ + CntrStartConf* conf = (CntrStartConf*)signal->getDataPtrSend(); + conf->startGci = 0; + conf->masterNodeId = node; + conf->noStartNodes = 1; + conf->startType = NodeState::ST_INITIAL_NODE_RESTART; + NodeBitmask mask; + mask.clear(); + mask.copyto(NdbNodeBitmask::Size, conf->startedNodes); + mask.clear(); + mask.set(cntr.getOwnNodeId()); + mask.copyto(NdbNodeBitmask::Size, conf->startingNodes); + cntr.execCNTR_START_CONF(signal); + return; + } + } + } + block.progError(0,0); } |