📄 dbtcmain.cpp
字号:
cmasterNodeId = readNodes->masterNodeId; con_lineNodes = 0; arrGuard(csystemnodes, MAX_NDB_NODES); guard0 = csystemnodes - 1; arrGuard(guard0, MAX_NDB_NODES); // Check not zero nodes for (unsigned i = 1; i < MAX_NDB_NODES; i++) { jam(); if (NodeBitmask::get(readNodes->allNodes, i)) { hostptr.i = i; ptrCheckGuard(hostptr, chostFilesize, hostRecord); if (NodeBitmask::get(readNodes->inactiveNodes, i)) { jam(); hostptr.p->hostStatus = HS_DEAD; } else { jam(); con_lineNodes++; hostptr.p->hostStatus = HS_ALIVE; c_alive_nodes.set(i); }//if }//if }//for ndbsttorry010Lab(signal);}//Dbtc::execREAD_NODESCONF()/*****************************************************************************//* A P I _ F A I L R E Q */// An API node has failed for some reason. We need to disconnect all API // connections to the API node. This also includes /*****************************************************************************/void Dbtc::execAPI_FAILREQ(Signal* signal){ /*************************************************************************** * Set the block reference to return API_FAILCONF to. Set the number of api * connects currently closing to one to indicate that we are still in the * process of going through the api connect records. Thus checking for zero * can only be true after all api connect records have been checked. **************************************************************************/ jamEntry(); capiFailRef = signal->theData[1]; arrGuard(signal->theData[0], MAX_NODES); capiConnectClosing[signal->theData[0]] = 1; handleFailedApiNode(signal, signal->theData[0], (UintR)0);}voidDbtc::handleFailedApiNode(Signal* signal, UintR TapiFailedNode, UintR TapiConnectPtr){ UintR TloopCount = 0; arrGuard(TapiFailedNode, MAX_NODES); apiConnectptr.i = TapiConnectPtr; do { ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref); if (TapiNode == TapiFailedNode) {#ifdef VM_TRACE if (apiConnectptr.p->apiFailState != ZFALSE) { ndbout << "Error in previous API fail handling discovered" << endl << " apiConnectptr.i = " << apiConnectptr.i << endl << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl << " ndbapiBlockref = " << hex << apiConnectptr.p->ndbapiBlockref << endl << " apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref) << endl; if (apiConnectptr.p->lastTcConnect != RNIL){ jam(); tcConnectptr.i = apiConnectptr.p->lastTcConnect; ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); ndbout << " tcConnectptr.i = " << tcConnectptr.i << endl << " tcConnectstate = " << tcConnectptr.p->tcConnectstate << endl; } }//if#endif apiConnectptr.p->returnsignal = RS_NO_RETURN; /***********************************************************************/ // The connected node is the failed node. /**********************************************************************/ switch(apiConnectptr.p->apiConnectstate) { case CS_DISCONNECTED: /*********************************************************************/ // These states do not need any special handling. // Simply continue with the next. /*********************************************************************/ jam(); break; case CS_ABORTING: /*********************************************************************/ // This could actually mean that the API connection is already // ready to release if the abortState is IDLE. /*********************************************************************/ if (apiConnectptr.p->abortState == AS_IDLE) { jam(); releaseApiCon(signal, apiConnectptr.i); } else { jam(); capiConnectClosing[TapiFailedNode]++; apiConnectptr.p->apiFailState = ZTRUE; }//if break; case CS_WAIT_ABORT_CONF: case CS_WAIT_COMMIT_CONF: case CS_START_COMMITTING: case CS_PREPARE_TO_COMMIT: case CS_COMMITTING: case CS_COMMIT_SENT: /*********************************************************************/ // These states indicate that an abort process or commit process is // already ongoing. We will set a state in the api record indicating // that the API node has failed. // Also we will increase the number of outstanding api records to // wait for before we can respond with API_FAILCONF. /*********************************************************************/ jam(); capiConnectClosing[TapiFailedNode]++; apiConnectptr.p->apiFailState = ZTRUE; break; case CS_START_SCAN: /*********************************************************************/ // The api record was performing a scan operation. We need to check // on the scan state. Since completing a scan process might involve // sending several signals we will increase the loop count by 64. /*********************************************************************/ jam(); apiConnectptr.p->apiFailState = ZTRUE; capiConnectClosing[TapiFailedNode]++; ScanRecordPtr scanPtr; scanPtr.i = apiConnectptr.p->apiScanRec; ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord); close_scan_req(signal, scanPtr, true); TloopCount += 64; break; case CS_CONNECTED: /*********************************************************************/ // The api record is connected to failed node. We need to release the // connection and set it in a disconnected state. /*********************************************************************/ jam(); releaseApiCon(signal, apiConnectptr.i); break; case CS_REC_COMMITTING: case CS_RECEIVING: case CS_STARTED: /*********************************************************************/ // The api record was in the process of performing a transaction but // had not yet sent all information. // We need to initiate an ABORT since the API will not provide any // more information. // Since the abort can send many signals we will insert a real-time // break after checking this record. /*********************************************************************/ jam(); apiConnectptr.p->apiFailState = ZTRUE; capiConnectClosing[TapiFailedNode]++; abort010Lab(signal); TloopCount = 256; break; case CS_PREPARED: jam(); case CS_REC_PREPARING: jam(); case CS_START_PREPARING: jam(); /*********************************************************************/ // Not implemented yet. /*********************************************************************/ systemErrorLab(signal, __LINE__); break; case CS_RESTART: jam(); case CS_COMPLETING: jam(); case CS_COMPLETE_SENT: jam(); case CS_WAIT_COMPLETE_CONF: jam(); case CS_FAIL_ABORTING: jam(); case CS_FAIL_ABORTED: jam(); case CS_FAIL_PREPARED: jam(); case CS_FAIL_COMMITTING: jam(); case CS_FAIL_COMMITTED: /*********************************************************************/ // These states are only valid on copy and fail API connections. /*********************************************************************/ default: jam(); systemErrorLab(signal, __LINE__); break; }//switch } else { jam(); }//if apiConnectptr.i++; if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) { jam(); /** * Finished with scanning connection record * * Now scan markers */ removeMarkerForFailedAPI(signal, TapiFailedNode, 0); return; }//if } while (TloopCount++ < 256); signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE; signal->theData[1] = TapiFailedNode; signal->theData[2] = apiConnectptr.i; sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);}//Dbtc::handleFailedApiNode()voidDbtc::removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 startBucket){ TcFailRecordPtr node_fail_ptr; node_fail_ptr.i = 0; ptrAss(node_fail_ptr, tcFailRecord); if(node_fail_ptr.p->failStatus != FS_IDLE) { jam(); DEBUG("Restarting removeMarkerForFailedAPI"); /** * TC take-over in progress * needs to restart as this * creates new markers */ signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS; signal->theData[1] = nodeId; signal->theData[2] = 0; sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3); return; } CommitAckMarkerIterator iter; m_commitAckMarkerHash.next(startBucket, iter); const Uint32 RT_BREAK = 256; for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){ jam(); if(iter.curr.i == RNIL){ jam(); /** * Done with iteration */ capiConnectClosing[nodeId]--; if (capiConnectClosing[nodeId] == 0) { jam(); /********************************************************************/ // No outstanding ABORT or COMMIT's of this failed API node. // We can respond with API_FAILCONF /********************************************************************/ signal->theData[0] = nodeId; signal->theData[1] = cownref; sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB); } return; } if(iter.curr.p->apiNodeId == nodeId){ jam(); /** * Check so that the record is not still in use * */ ApiConnectRecordPtr apiConnectPtr; apiConnectPtr.i = iter.curr.p->apiConnectPtr; ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord); if(apiConnectPtr.p->commitAckMarker == iter.curr.i){ jam(); /** * The record is still active * * Don't remove it, but continueb instead */ break; } sendRemoveMarkers(signal, iter.curr.p); m_commitAckMarkerHash.release(iter.curr); break; } m_commitAckMarkerHash.next(iter); } signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS; signal->theData[1] = nodeId; signal->theData[2] = iter.bucket; sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);}void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr){ ApiConnectRecordPtr TlocalApiConnectptr; UintR TfailedApiNode; TlocalApiConnectptr.i = TapiConnectptr; ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord); TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref); arrGuard(TfailedApiNode, MAX_NODES); capiConnectClosing[TfailedApiNode]--; releaseApiCon(signal, TapiConnectptr); TlocalApiConnectptr.p->apiFailState = ZFALSE; if (capiConnectClosing[TfailedApiNode] == 0) { jam(); signal->theData[0] = TfailedApiNode; signal->theData[1] = cownref; sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB); }//if}//Dbtc::handleApiFailState()/**************************************************************************** * T C S E I Z E R E Q * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A * TRANSACTION * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK ****************************************************************************/void Dbtc::execTCSEIZEREQ(Signal* signal) { UintR tapiPointer; BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/ jamEntry(); tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/ tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/ const NodeState::StartLevel sl = (NodeState::StartLevel)getNodeState().startLevel; const NodeId senderNodeId = refToNode(tapiBlockref); const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0; if(!(senderNodeId == getNodeState().getSingleUserApi()) && !getNodeState().getSingleUserMode()) { if(!(sl==NodeState::SL_SINGLEUSER && senderNodeId == getNodeState().getSingleUserApi())) { if (!(sl == NodeState::SL_STARTED || (sl == NodeState::SL_STARTING && local == true))) { jam(); Uint32 errCode; if(!(sl == NodeState::SL_SINGLEUSER && local)) { switch(sl){ case NodeState::SL_STARTING: errCode = ZSYSTEM_NOT_STARTED_ERROR; break; case NodeState::SL_STOPPING_1: case NodeState::SL_STOPPING_2: case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_4: if(getNodeState().stopping.systemShutdown) errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS; else errCode = ZNODE_SHUTDOWN_IN_PROGRESS; break; case NodeState::SL_SINGLEUSER: errCode = ZCLUSTER_IN_SINGLEUSER_MODE; break; default: errCode = ZWRONG_STATE; break; } signal->theData[0] = tapiPointer; signal->theData[1] = errCode; sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB); return; }//if (!(sl == SL_SINGLEUSER)) } //if } } seizeApiConnect(signal); if (terrorCode == ZOK) { jam(); apiConnectptr.p->ndbapiConnect = tapiPointer; apiConnectptr.p->ndbapiBlockref = tapiBlockref; signal->theData[0] = apiConnectptr.p->ndbapiConnect; signal->theData[1] = apiConnectptr.i; sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 2, JBB); return; } signal->theData[0] = tapiPointer; signal->theData[1] = terrorCode; sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);}//Dbtc::execTCSEIZEREQ()/****************************************************************************//* T C R E L E A S E Q *//* REQUEST TO RELEASE A CONNECT RECORD *//****************************************************************************/void Dbtc::execTCRELEASEREQ(Signal* signal) { UintR tapiPointer; BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/ jamEntry(); tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/ tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/ tuserpointer = signal->theData[2]; if (tapiPointer >= capiConnectFilesize) { jam(); signal->theData[0] = tuserpointer; signal->theData[1] = ZINVALID_CONNECTION; signal->theData[2] = __LINE__; sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB); return; } else { jam(); apiConnectptr.i = tapiPointer; }//if ptrAss(apiConnectptr, apiConnectRecord); if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) { jam(); signal->theData[0] = tuserpointer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -