void ClusterMgr::reportNodeFailed(NodeId nodeId, bool disconnect){ Node & theNode = theNodes[nodeId]; set_node_alive(theNode, false); theNode.m_info.m_connectCount ++; if(theNode.connected) { theFacade.doDisconnect(nodeId); } const bool report = (theNode.m_state.startLevel != NodeState::SL_NOTHING); theNode.m_state.startLevel = NodeState::SL_NOTHING; if(disconnect || report) { theFacade.ReportNodeDead(nodeId); } theNode.nfCompleteRep = false; if(noOfAliveNodes == 0) { if (!global_flag_skip_invalidate_cache) { theFacade.m_globalDictCache.lock(); theFacade.m_globalDictCache.invalidate_all(); theFacade.m_globalDictCache.unlock(); m_connect_count ++; m_cluster_state = CS_waiting_for_clean_cache; } NFCompleteRep rep; for(Uint32 i = 1; i<MAX_NODES; i++){ if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){ rep.failedNodeId = i; execNF_COMPLETEREP((Uint32*)&rep); } } } }
/** * We're holding the trp_client lock while performing poll from * ClusterMgr. So we always execute all the execSIGNAL-methods in * ClusterMgr with protection other methods that use the trp_client * lock (reportDisconnect, reportConnect, is_cluster_completely_unavailable, * ArbitMgr (sendSignalToQmgr)). */ void ClusterMgr::trp_deliver_signal(const NdbApiSignal* sig, const LinearSectionPtr ptr[3]) { const Uint32 gsn = sig->theVerId_signalNumber; const Uint32 * theData = sig->getDataPtr(); switch (gsn) { case GSN_API_REGREQ: execAPI_REGREQ(theData); break; case GSN_API_REGCONF: execAPI_REGCONF(sig, ptr); break; case GSN_API_REGREF: execAPI_REGREF(theData); break; case GSN_NODE_FAILREP: execNODE_FAILREP(sig, ptr); break; case GSN_NF_COMPLETEREP: execNF_COMPLETEREP(sig, ptr); break; case GSN_ARBIT_STARTREQ: if (theArbitMgr != NULL) theArbitMgr->doStart(theData); break; case GSN_ARBIT_CHOOSEREQ: if (theArbitMgr != NULL) theArbitMgr->doChoose(theData); break; case GSN_ARBIT_STOPORD: if(theArbitMgr != NULL) theArbitMgr->doStop(theData); break; case GSN_ALTER_TABLE_REP: { if (theFacade.m_globalDictCache == NULL) break; const AlterTableRep* rep = (const AlterTableRep*)theData; theFacade.m_globalDictCache->lock(); theFacade.m_globalDictCache-> alter_table_rep((const char*)ptr[0].p, rep->tableId, rep->tableVersion, rep->changeType == AlterTableRep::CT_ALTERED); theFacade.m_globalDictCache->unlock(); break; } case GSN_SUB_GCP_COMPLETE_REP: { /** * Report */ theFacade.for_each(this, sig, ptr); /** * Reply */ { BlockReference ownRef = numberToRef(API_CLUSTERMGR, theFacade.ownId()); NdbApiSignal tSignal(* sig); Uint32* send= tSignal.getDataPtrSend(); memcpy(send, theData, tSignal.getLength() << 2); CAST_PTR(SubGcpCompleteAck, send)->rep.senderRef = ownRef; Uint32 ref= sig->theSendersBlockRef; Uint32 aNodeId= refToNode(ref); tSignal.theReceiversBlockNumber= refToBlock(ref); tSignal.theVerId_signalNumber= GSN_SUB_GCP_COMPLETE_ACK; tSignal.theSendersBlockRef = API_CLUSTERMGR; safe_noflush_sendSignal(&tSignal, aNodeId); } break; } case GSN_TAKE_OVERTCCONF: { /** * Report */ theFacade.for_each(this, sig, ptr); return; } case GSN_CONNECT_REP: { execCONNECT_REP(sig, ptr); return; } case GSN_DISCONNECT_REP: { execDISCONNECT_REP(sig, ptr); return; } case GSN_CLOSE_COMREQ: { theFacade.perform_close_clnt(this); return; } case GSN_EXPAND_CLNT: { theFacade.expand_clnt(); return; } default: break; } return; }
void ClusterMgr::execNODE_FAILREP(const NdbApiSignal* sig, const LinearSectionPtr ptr[]) { const NodeFailRep * rep = CAST_CONSTPTR(NodeFailRep, sig->getDataPtr()); NodeBitmask mask; if (sig->getLength() == NodeFailRep::SignalLengthLong) { mask.assign(NodeBitmask::Size, rep->theAllNodes); } else { mask.assign(NdbNodeBitmask::Size, rep->theNodes); } NdbApiSignal signal(sig->theSendersBlockRef); signal.theVerId_signalNumber = GSN_NODE_FAILREP; signal.theReceiversBlockNumber = API_CLUSTERMGR; signal.theTrace = 0; signal.theLength = NodeFailRep::SignalLengthLong; NodeFailRep * copy = CAST_PTR(NodeFailRep, signal.getDataPtrSend()); copy->failNo = 0; copy->masterNodeId = 0; copy->noOfNodes = 0; NodeBitmask::clear(copy->theAllNodes); for (Uint32 i = mask.find_first(); i != NodeBitmask::NotFound; i = mask.find_next(i + 1)) { Node & cm_node = theNodes[i]; trp_node & theNode = cm_node; bool node_failrep = theNode.m_node_fail_rep; bool connected = theNode.is_connected(); set_node_dead(theNode); if (node_failrep == false) { theNode.m_node_fail_rep = true; NodeBitmask::set(copy->theAllNodes, i); copy->noOfNodes++; } if (connected) { theFacade.doDisconnect(i); } } recalcMinDbVersion(); if (copy->noOfNodes) { theFacade.for_each(this, &signal, 0); // report GSN_NODE_FAILREP } if (noOfAliveNodes == 0) { NdbApiSignal signal(numberToRef(API_CLUSTERMGR, getOwnNodeId())); signal.theVerId_signalNumber = GSN_NF_COMPLETEREP; signal.theReceiversBlockNumber = 0; signal.theTrace = 0; signal.theLength = NFCompleteRep::SignalLength; NFCompleteRep * rep = CAST_PTR(NFCompleteRep, signal.getDataPtrSend()); rep->blockNo =0; rep->nodeId = getOwnNodeId(); rep->unused = 0; rep->from = __LINE__; for (Uint32 i = 1; i < MAX_NODES; i++) { trp_node& theNode = theNodes[i]; if (theNode.defined && theNode.nfCompleteRep == false) { rep->failedNodeId = i; execNF_COMPLETEREP(&signal, 0); } } } }