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); } } } }
void ClusterMgr::execAPI_REGCONF(const NdbApiSignal * signal, const LinearSectionPtr ptr[]) { const ApiRegConf * apiRegConf = CAST_CONSTPTR(ApiRegConf, signal->getDataPtr()); const NodeId nodeId = refToNode(apiRegConf->qmgrRef); #ifdef DEBUG_REG ndbout_c("ClusterMgr: Recd API_REGCONF from node %d", nodeId); #endif assert(nodeId > 0 && nodeId < MAX_NODES); Node & cm_node = theNodes[nodeId]; trp_node & node = cm_node; assert(node.defined == true); assert(node.is_connected() == true); if(node.m_info.m_version != apiRegConf->version) { node.m_info.m_version = apiRegConf->version; node.m_info.m_mysql_version = apiRegConf->mysql_version; if (node.m_info.m_version < NDBD_SPLIT_VERSION) node.m_info.m_mysql_version = 0; if(theNodes[theFacade.ownId()].m_info.m_type == NodeInfo::MGM) node.compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, node.m_info.m_version); else node.compatible = ndbCompatible_api_ndb(NDB_VERSION, node.m_info.m_version); } node.set_confirmed(true); if (node.minDbVersion != apiRegConf->minDbVersion) { node.minDbVersion = apiRegConf->minDbVersion; recalcMinDbVersion(); } if (node.m_info.m_version >= NDBD_255_NODES_VERSION) { node.m_state = apiRegConf->nodeState; } else { /** * from 2 to 8 words = 6 words diff, 6*4 = 24 */ memcpy(&node.m_state, &apiRegConf->nodeState, sizeof(node.m_state) - 24); } if (node.m_info.m_type == NodeInfo::DB) { /** * Only set DB nodes to "alive" */ if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED || node.m_state.getSingleUserMode())) { set_node_alive(node, true); } else { set_node_alive(node, false); } } cm_node.hbMissed = 0; cm_node.hbCounter = 0; /* By convention, conf->apiHeartbeatFrequency is in centiseconds rather than milliseconds. See also Qmgr::sendApiRegConf(). */ const Int64 freq = (static_cast<Int64>(apiRegConf->apiHeartbeatFrequency) * 10) - 50; if (freq > UINT_MAX32) { // In case of overflow. assert(false); /* Note this assert fails on some upgrades... */ cm_node.hbFrequency = UINT_MAX32; } else if (freq < minHeartBeatInterval) { /** * We use minHeartBeatInterval as a lower limit. This also prevents * against underflow. */ cm_node.hbFrequency = minHeartBeatInterval; } else { cm_node.hbFrequency = static_cast<Uint32>(freq); } // If responding nodes indicates that it is connected to other // nodes, that makes it probable that those nodes are alive and // available also for this node. for (int db_node_id = 1; db_node_id <= MAX_DATA_NODE_ID; db_node_id ++) { if (node.m_state.m_connected_nodes.get(db_node_id)) { // Tell this nodes start clients thread that db_node_id // is up and probable connectable. theFacade.theTransporterRegistry->indicate_node_up(db_node_id); } } // Distribute signal to all threads/blocks // TODO only if state changed... theFacade.for_each(this, signal, ptr); }
void ClusterMgr::execAPI_REGCONF(const NdbApiSignal * signal, const LinearSectionPtr ptr[]) { const ApiRegConf * apiRegConf = CAST_CONSTPTR(ApiRegConf, signal->getDataPtr()); const NodeId nodeId = refToNode(apiRegConf->qmgrRef); #ifdef DEBUG_REG ndbout_c("ClusterMgr: Recd API_REGCONF from node %d", nodeId); #endif assert(nodeId > 0 && nodeId < MAX_NODES); Node & cm_node = theNodes[nodeId]; trp_node & node = cm_node; assert(node.defined == true); assert(node.is_connected() == true); if(node.m_info.m_version != apiRegConf->version){ node.m_info.m_version = apiRegConf->version; node.m_info.m_mysql_version = apiRegConf->mysql_version; if (node.m_info.m_version < NDBD_SPLIT_VERSION) node.m_info.m_mysql_version = 0; if(theNodes[theFacade.ownId()].m_info.m_type == NodeInfo::MGM) node.compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, node.m_info.m_version); else node.compatible = ndbCompatible_api_ndb(NDB_VERSION, node.m_info.m_version); } node.set_confirmed(true); if (node.minDbVersion != apiRegConf->minDbVersion) { node.minDbVersion = apiRegConf->minDbVersion; recalcMinDbVersion(); } if (node.m_info.m_version >= NDBD_255_NODES_VERSION) { node.m_state = apiRegConf->nodeState; } else { /** * from 2 to 8 words = 6 words diff, 6*4 = 24 */ memcpy(&node.m_state, &apiRegConf->nodeState, sizeof(node.m_state) - 24); } if (node.m_info.m_type == NodeInfo::DB) { /** * Only set DB nodes to "alive" */ if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED || node.m_state.getSingleUserMode())) { set_node_alive(node, true); } else { set_node_alive(node, false); } } cm_node.hbMissed = 0; cm_node.hbCounter = 0; cm_node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50; // Distribute signal to all threads/blocks // TODO only if state changed... theFacade.for_each(this, signal, ptr); check_wait_for_hb(nodeId); }