storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp (2,956 lines of code) (raw):

/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define NDBCNTR_C #include "Ndbcntr.hpp" #include <ndb_limits.h> #include <ndb_version.h> #include <SimpleProperties.hpp> #include <signaldata/DictTabInfo.hpp> #include <signaldata/SchemaTrans.hpp> #include <signaldata/CreateTable.hpp> #include <signaldata/CreateHashMap.hpp> #include <signaldata/ReadNodesConf.hpp> #include <signaldata/NodeFailRep.hpp> #include <signaldata/TcKeyReq.hpp> #include <signaldata/TcKeyConf.hpp> #include <signaldata/EventReport.hpp> #include <signaldata/NodeStateSignalData.hpp> #include <signaldata/StopPerm.hpp> #include <signaldata/StopMe.hpp> #include <signaldata/WaitGCP.hpp> #include <signaldata/CheckNodeGroups.hpp> #include <signaldata/StartOrd.hpp> #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 <signaldata/FailRep.hpp> #include <AttributeHeader.hpp> #include <Configuration.hpp> #include <DebuggerNames.hpp> #include <signaldata/DihRestart.hpp> #include <NdbOut.hpp> #include <NdbTick.h> #include <signaldata/TakeOver.hpp> #include <signaldata/CreateNodegroupImpl.hpp> #include <signaldata/DropNodegroupImpl.hpp> #include <signaldata/CreateFilegroup.hpp> #include <EventLogger.hpp> extern EventLogger * g_eventLogger; // used during shutdown for reporting current startphase // accessed from Emulator.cpp, NdbShutdown() Uint32 g_currentStartPhase; /** * ALL_BLOCKS Used during start phases and while changing node state * * NDBFS_REF Has to be before NDBCNTR_REF (due to "ndb -i" stuff) */ struct BlockInfo { BlockReference Ref; // BlockReference Uint32 NextSP; // Next start phase Uint32 ErrorInsertStart; Uint32 ErrorInsertStop; }; static BlockInfo ALL_BLOCKS[] = { { NDBFS_REF, 0 , 2000, 2999 }, { 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 }, { NDBCNTR_REF, 0 , 1000, 1999 }, { CMVMI_REF, 1 , 9000, 9999 }, // before QMGR { QMGR_REF, 1 , 1, 999 }, { TRIX_REF, 1 , 0, 0 }, { BACKUP_REF, 1 , 10000, 10999 }, { DBUTIL_REF, 1 , 11000, 11999 }, { SUMA_REF, 1 , 13000, 13999 }, { DBTUX_REF, 1 , 12000, 12999 } ,{ TSMAN_REF, 1 , 0, 0 } ,{ LGMAN_REF, 1 , 0, 0 } ,{ PGMAN_REF, 1 , 0, 0 } ,{ RESTORE_REF,1 , 0, 0 } ,{ DBINFO_REF,1 , 0, 0 } ,{ DBSPJ_REF,1 , 0, 0 } }; static const Uint32 ALL_BLOCKS_SZ = sizeof(ALL_BLOCKS)/sizeof(BlockInfo); static BlockReference readConfigOrder[ALL_BLOCKS_SZ] = { CMVMI_REF, NDBFS_REF, DBINFO_REF, DBTUP_REF, DBACC_REF, DBTC_REF, DBLQH_REF, DBTUX_REF, DBDICT_REF, DBDIH_REF, NDBCNTR_REF, QMGR_REF, TRIX_REF, BACKUP_REF, DBUTIL_REF, SUMA_REF, TSMAN_REF, LGMAN_REF, PGMAN_REF, RESTORE_REF, DBSPJ_REF }; /*******************************/ /* CONTINUEB */ /*******************************/ void Ndbcntr::execCONTINUEB(Signal* signal) { jamEntry(); UintR Ttemp1 = signal->theData[0]; switch (Ttemp1) { case ZSTARTUP:{ if(getNodeState().startLevel == NodeState::SL_STARTED){ jam(); return; } if(cmasterNodeId == getOwnNodeId() && c_start.m_starting.isclear()){ jam(); trySystemRestart(signal); // Fall-through } Uint64 now = NdbTick_CurrentMillisecond(); if(now > c_start.m_startFailureTimeout) { jam(); Uint32 to_3= 0; const ndb_mgm_configuration_iterator * p = m_ctx.m_config.getOwnConfigIterator(); ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3); BaseString tmp; tmp.append("Shutting down node as total restart time exceeds " " StartFailureTimeout as set in config file "); if(to_3 == 0) tmp.append(" 0 (inifinite)"); else tmp.appfmt(" %d", to_3); progError(__LINE__, NDBD_EXIT_RESTART_TIMEOUT, tmp.c_str()); } signal->theData[0] = ZSTARTUP; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1); break; } case ZSHUTDOWN: jam(); c_stopRec.checkTimeout(signal); break; case ZBLOCK_STTOR: if (ERROR_INSERTED(1002)) { signal->theData[0] = ZBLOCK_STTOR; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); return; } else { c_missra.sendNextSTTOR(signal); } return; default: jam(); systemErrorLab(signal, __LINE__); return; break; }//switch }//Ndbcntr::execCONTINUEB() void Ndbcntr::execAPI_START_REP(Signal* signal) { if(refToBlock(signal->getSendersBlockRef()) == QMGR) { for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){ sendSignal(ALL_BLOCKS[i].Ref, GSN_API_START_REP, signal, 1, JBB); } } } /*******************************/ /* SYSTEM_ERROR */ /*******************************/ void Ndbcntr::execSYSTEM_ERROR(Signal* signal) { const SystemError * const sysErr = (SystemError *)signal->getDataPtr(); char buf[100]; int killingNode = refToNode(sysErr->errorRef); Uint32 data1 = sysErr->data[0]; jamEntry(); switch (sysErr->errorCode){ case SystemError::GCPStopDetected: { BaseString::snprintf(buf, sizeof(buf), "Node %d killed this node because " "GCP stop was detected", killingNode); signal->theData[0] = 7025; EXECUTE_DIRECT(DBDIH, GSN_DUMP_STATE_ORD, signal, 1); jamEntry(); { signal->theData[0] = 12002; EXECUTE_DIRECT(LGMAN, GSN_DUMP_STATE_ORD, signal, 1, 0); } jamEntry(); break; } case SystemError::CopyFragRefError: CRASH_INSERTION(1000); BaseString::snprintf(buf, sizeof(buf), "Killed by node %d as " "copyfrag failed, error: %u", killingNode, data1); break; case SystemError::StartFragRefError: BaseString::snprintf(buf, sizeof(buf), "Node %d killed this node because " "it replied StartFragRef error code: %u.", killingNode, data1); break; case SystemError::CopySubscriptionRef: BaseString::snprintf(buf, sizeof(buf), "Node %d killed this node because " "it could not copy a subscription during node restart. " "Copy subscription error code: %u.", killingNode, data1); break; case SystemError::CopySubscriberRef: BaseString::snprintf(buf, sizeof(buf), "Node %d killed this node because " "it could not start a subscriber during node restart. " "Copy subscription error code: %u.", killingNode, data1); break; default: BaseString::snprintf(buf, sizeof(buf), "System error %d, " " this node was killed by node %d", sysErr->errorCode, killingNode); break; } progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR, buf); return; }//Ndbcntr::execSYSTEM_ERROR() struct ddentry { Uint32 type; const char * name; Uint64 size; }; /** * f_dd[] = { * { DictTabInfo::LogfileGroup, "DEFAULT-LG", 32*1024*1024 }, * { DictTabInfo::Undofile, "undofile.dat", 64*1024*1024 }, * { DictTabInfo::Tablespace, "DEFAULT-TS", 1024*1024 }, * { DictTabInfo::Datafile, "datafile.dat", 64*1024*1024 }, * { ~0, 0, 0 } * }; */ Vector<ddentry> f_dd; Uint64 parse_size(const char * src) { Uint64 num = 0; char * endptr = 0; num = strtoll(src, &endptr, 10); if (endptr) { switch(* endptr){ case 'k': case 'K': num *= 1024; break; case 'm': case 'M': num *= 1024; num *= 1024; break; case 'g': case 'G': num *= 1024; num *= 1024; num *= 1024; break; } } return num; } static int parse_spec(Vector<ddentry> & dst, const char * src, Uint32 type) { const char * key; Uint32 filetype; struct ddentry group; if (type == DictTabInfo::LogfileGroup) { key = "undo_buffer_size="; group.size = 64*1024*1024; group.name = "DEFAULT-LG"; group.type = type; filetype = DictTabInfo::Undofile; } else { key = "extent_size="; group.size = 1024*1024; group.name = "DEFAULT-TS"; group.type = type; filetype = DictTabInfo::Datafile; } size_t keylen = strlen(key); BaseString arg(src); Vector<BaseString> list; arg.split(list, ";"); bool first = true; for (Uint32 i = 0; i<list.size(); i++) { list[i].trim(); if (strncasecmp(list[i].c_str(), "name=", sizeof("name=")-1) == 0) { group.name= strdup(list[i].c_str() + sizeof("name=")-1); } else if (strncasecmp(list[i].c_str(), key, keylen) == 0) { group.size = parse_size(list[i].c_str() + keylen); } else if (strlen(list[i].c_str()) == 0 && (i + 1) == list.size()) { /** * ignore stray ";" */ } else { /** * interpret as filespec */ struct ddentry entry; const char * path = list[i].c_str(); char * sizeptr = const_cast<char*>(strchr(path, ':')); if (sizeptr == 0) { return -1; } * sizeptr = 0; entry.name = strdup(path); entry.size = parse_size(sizeptr + 1); entry.type = filetype; if (first) { /** * push group aswell */ first = false; dst.push_back(group); } dst.push_back(entry); } } return 0; } void Ndbcntr::execREAD_CONFIG_REQ(Signal* signal) { jamEntry(); const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr(); Uint32 ref = req->senderRef; Uint32 senderData = req->senderData; const ndb_mgm_configuration_iterator * p = m_ctx.m_config.getOwnConfigIterator(); ndbrequire(p != 0); Uint32 dl = 0; ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl); if (dl == 0) { const char * lgspec = 0; char buf[1024]; if (!ndb_mgm_get_string_parameter(p, CFG_DB_DD_LOGFILEGROUP_SPEC, &lgspec)) { jam(); if (parse_spec(f_dd, lgspec, DictTabInfo::LogfileGroup)) { BaseString::snprintf(buf, sizeof(buf), "Unable to parse InitialLogfileGroup: %s", lgspec); progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf); } } const char * tsspec = 0; if (!ndb_mgm_get_string_parameter(p, CFG_DB_DD_TABLEPACE_SPEC, &tsspec)) { if (f_dd.size() == 0) { warningEvent("InitialTablespace specified, " "but InitialLogfileGroup is not!"); warningEvent("Ignoring InitialTablespace: %s", tsspec); } else { if (parse_spec(f_dd, tsspec, DictTabInfo::Tablespace)) { BaseString::snprintf(buf, sizeof(buf), "Unable to parse InitialTablespace: %s", tsspec); progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf); } } } } struct ddentry empty; empty.type = ~0; f_dd.push_back(empty); if (true) { // TODO: add config parameter // remove ATTRIBUTE_MASK2 g_sysTable_NDBEVENTS_0.columnCount--; } ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend(); conf->senderRef = reference(); conf->senderData = senderData; sendSignal(ref, GSN_READ_CONFIG_CONF, signal, ReadConfigConf::SignalLength, JBB); } void Ndbcntr::execSTTOR(Signal* signal) { jamEntry(); cstartPhase = signal->theData[1]; cndbBlocksCount = 0; cinternalStartphase = cstartPhase - 1; switch (cstartPhase) { case 0: if(m_ctx.m_config.getInitialStart()){ jam(); c_fsRemoveCount = 0; clearFilesystem(signal); return; } sendSttorry(signal); break; case ZSTART_PHASE_1: jam(); startPhase1Lab(signal); break; case ZSTART_PHASE_2: jam(); startPhase2Lab(signal); break; case ZSTART_PHASE_3: jam(); startPhase3Lab(signal); break; case ZSTART_PHASE_4: jam(); startPhase4Lab(signal); break; case ZSTART_PHASE_5: jam(); startPhase5Lab(signal); break; case 6: jam(); getNodeGroup(signal); sendSttorry(signal); break; case ZSTART_PHASE_8: jam(); startPhase8Lab(signal); break; case ZSTART_PHASE_9: jam(); startPhase9Lab(signal); break; default: jam(); sendSttorry(signal); break; }//switch }//Ndbcntr::execSTTOR() void Ndbcntr::getNodeGroup(Signal* signal){ jam(); CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend(); sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::GetNodeGroup; EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal, CheckNodeGroups::SignalLength); jamEntry(); c_nodeGroup = sd->output; } /*******************************/ /* NDB_STTORRY */ /*******************************/ void Ndbcntr::execNDB_STTORRY(Signal* signal) { jamEntry(); switch (cstartPhase) { case ZSTART_PHASE_2: jam(); ph2GLab(signal); return; break; case ZSTART_PHASE_3: jam(); ph3ALab(signal); return; break; case ZSTART_PHASE_4: jam(); ph4BLab(signal); return; break; case ZSTART_PHASE_5: jam(); ph5ALab(signal); return; break; case ZSTART_PHASE_6: jam(); ph6ALab(signal); return; break; case ZSTART_PHASE_7: jam(); ph6BLab(signal); return; break; case ZSTART_PHASE_8: jam(); ph7ALab(signal); return; break; case ZSTART_PHASE_9: jam(); ph8ALab(signal); return; break; default: jam(); systemErrorLab(signal, __LINE__); return; break; }//switch }//Ndbcntr::execNDB_STTORRY() void Ndbcntr::startPhase1Lab(Signal* signal) { jamEntry(); initData(signal); cdynamicNodeId = 0; NdbBlocksRecPtr ndbBlocksPtr; ndbBlocksPtr.i = 0; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBLQH_REF; ndbBlocksPtr.i = 1; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBDICT_REF; ndbBlocksPtr.i = 2; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBTUP_REF; ndbBlocksPtr.i = 3; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBACC_REF; ndbBlocksPtr.i = 4; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBTC_REF; ndbBlocksPtr.i = 5; ptrAss(ndbBlocksPtr, ndbBlocksRec); ndbBlocksPtr.p->blockref = DBDIH_REF; sendSttorry(signal); return; } void Ndbcntr::execREAD_NODESREF(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execREAD_NODESREF() /*******************************/ /* NDB_STARTREF */ /*******************************/ void Ndbcntr::execNDB_STARTREF(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execNDB_STARTREF() /*******************************/ /* STTOR */ /*******************************/ void Ndbcntr::startPhase2Lab(Signal* signal) { c_start.m_lastGci = 0; c_start.m_lastGciNodeId = getOwnNodeId(); DihRestartReq * req = CAST_PTR(DihRestartReq, signal->getDataPtrSend()); req->senderRef = reference(); sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, DihRestartReq::SignalLength, JBB); return; }//Ndbcntr::startPhase2Lab() /*******************************/ /* DIH_RESTARTCONF */ /*******************************/ void Ndbcntr::execDIH_RESTARTCONF(Signal* signal) { jamEntry(); const DihRestartConf * conf = CAST_CONSTPTR(DihRestartConf, signal->getDataPtrSend()); c_start.m_lastGci = conf->latest_gci; ctypeOfStart = NodeState::ST_SYSTEM_RESTART; cdihStartType = ctypeOfStart; ph2ALab(signal); return; }//Ndbcntr::execDIH_RESTARTCONF() /*******************************/ /* DIH_RESTARTREF */ /*******************************/ void Ndbcntr::execDIH_RESTARTREF(Signal* signal) { jamEntry(); ctypeOfStart = NodeState::ST_INITIAL_START; cdihStartType = ctypeOfStart; ph2ALab(signal); return; }//Ndbcntr::execDIH_RESTARTREF() void Ndbcntr::ph2ALab(Signal* signal) { /******************************/ /* request configured nodes */ /* from QMGR */ /* READ_NODESREQ */ /******************************/ 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 ~(Uint64)0; return time + timeoutValue; } /*******************************/ /* READ_NODESCONF */ /*******************************/ void Ndbcntr::execREAD_NODESCONF(Signal* signal) { jamEntry(); const ReadNodesConf * readNodes = (ReadNodesConf *)&signal->theData[0]; cmasterNodeId = readNodes->masterNodeId; cdynamicNodeId = readNodes->ndynamicId; /** * All defined nodes... */ c_allDefinedNodes.assign(NdbNodeBitmask::Size, readNodes->allNodes); c_clusterNodes.assign(NdbNodeBitmask::Size, readNodes->clusterNodes); Uint32 to_1 = 30000; Uint32 to_2 = 0; Uint32 to_3 = 0; const ndb_mgm_configuration_iterator * p = m_ctx.m_config.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_startTime = NdbTick_CurrentMillisecond(); 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); sendCntrStartReq(signal); signal->theData[0] = ZSTARTUP; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1); return; } void Ndbcntr::execCM_ADD_REP(Signal* signal){ jamEntry(); c_clusterNodes.set(signal->theData[0]); } void Ndbcntr::sendCntrStartReq(Signal * signal){ jamEntry(); 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); } void Ndbcntr::execCNTR_START_REF(Signal * signal){ jamEntry(); const CntrStartRef * ref = (CntrStartRef*)signal->getDataPtr(); switch(ref->errorCode){ case CntrStartRef::NotMaster: jam(); cmasterNodeId = ref->masterNodeId; sendCntrStartReq(signal); return; case CntrStartRef::StopInProgress: jam(); progError(__LINE__, NDBD_EXIT_RESTART_DURING_SHUTDOWN); } ndbrequire(false); } void Ndbcntr::StartRecord::reset(){ m_starting.clear(); m_waiting.clear(); m_withLog.clear(); m_withoutLog.clear(); m_waitTO.clear(); m_lastGci = m_lastGciNodeId = 0; m_startPartialTimeout = ~0; m_startPartitionedTimeout = ~0; m_startFailureTimeout = ~0; m_logNodesCount = 0; bzero(m_wait_sp, sizeof(m_wait_sp)); } void Ndbcntr::execCNTR_START_CONF(Signal * signal){ jamEntry(); const CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr(); cnoStartNodes = conf->noStartNodes; ctypeOfStart = (NodeState::StartType)conf->startType; cdihStartType = ctypeOfStart; 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); m_cntr_start_conf = true; ph2GLab(signal); } /** * 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 #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); /** * Inform all interested blocks that node has started */ for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){ sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_START_REP, signal, 1, JBB); } signal->theData[0] = nodeId; execSTART_PERMREP(signal); } void Ndbcntr::execSTART_PERMREP(Signal* signal) { Uint32 nodeId = signal->theData[0]; c_startedNodes.set(nodeId); c_start.m_starting.clear(nodeId); if(!c_start.m_starting.isclear()){ jam(); return; } if(cmasterNodeId != getOwnNodeId()){ jam(); c_start.reset(); return; } if(c_start.m_waiting.isclear()){ jam(); c_start.reset(); return; } startWaitingNodes(signal); } void Ndbcntr::execCNTR_START_REQ(Signal * signal){ jamEntry(); const CntrStartReq * req = (CntrStartReq*)signal->getDataPtr(); const Uint32 nodeId = req->nodeId; const Uint32 lastGci = req->lastGci; const NodeState::StartType st = (NodeState::StartType)req->startType; if(cmasterNodeId == 0){ jam(); // Has not completed READNODES yet sendSignalWithDelay(reference(), GSN_CNTR_START_REQ, signal, 100, signal->getLength()); return; } if(cmasterNodeId != getOwnNodeId()){ jam(); sendCntrStartRef(signal, nodeId, CntrStartRef::NotMaster); return; } const NodeState & nodeState = getNodeState(); switch(nodeState.startLevel){ case NodeState::SL_NOTHING: case NodeState::SL_CMVMI: jam(); ndbrequire(false); case NodeState::SL_STARTING: case NodeState::SL_STARTED: jam(); 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: jam(); c_start.m_withoutLog.set(nodeId); break; case NodeState::ST_SYSTEM_RESTART: jam(); c_start.m_withLog.set(nodeId); if(starting && lastGci > c_start.m_lastGci){ jam(); 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(starting){ jam(); 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: case NodeState::ST_ILLEGAL_TYPE: ndbrequire(false); } const bool startInProgress = !c_start.m_starting.isclear(); if((starting && startInProgress) || (startInProgress && !parallellNR)){ jam(); // We're already starting together with a bunch of nodes // Let this node wait... return; } if(starting){ jam(); trySystemRestart(signal); } else { jam(); startWaitingNodes(signal); } return; } void Ndbcntr::startWaitingNodes(Signal * signal){ #if ! PARALLELL_NR if (!c_start.m_waitTO.isclear()) { jam(); { char buf[100]; ndbout_c("starting (TO) %s", c_start.m_waitTO.getText(buf)); } /** * TO during SR * this can run in parallel (nowadays :-) */ NodeReceiverGroup rg(NDBCNTR, c_start.m_waitTO); c_start.m_starting.bitOR(c_start.m_waitTO); c_start.m_waiting.bitANDC(c_start.m_waitTO); c_start.m_waitTO.clear(); /** * They are stuck in CntrWaitRep::ZWAITPOINT_4_1 * have all meta data ok...but needs START_COPYREQ */ CntrWaitRep* rep = (CntrWaitRep*)signal->getDataPtrSend(); rep->nodeId = getOwnNodeId(); rep->waitPoint = CntrWaitRep::ZWAITPOINT_4_2_TO; sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); return; } 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)) { jam(); 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()){ jam(); 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()){ jam(); 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; } 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); if(!allClusterNodes){ jam(); return false; } NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART; if(c_start.m_waiting.equal(c_start.m_withoutLog)) { jam(); 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; case CheckNodeGroups::Partitioning: jam(); bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0); if(allNodes){ if(allowPartition){ jam(); break; } ndbrequire(false); // All nodes -> partitioning, which is not allowed } 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; } void Ndbcntr::ph2GLab(Signal* signal) { if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if sendSttorry(signal); return; }//Ndbcntr::ph2GLab() /* 4.4 START PHASE 3 */ /*###########################################################################*/ // SEND SIGNAL NDBSTTOR TO ALL BLOCKS, ACC, DICT, DIH, LQH, TC AND TUP // WHEN ALL BLOCKS HAVE RETURNED THEIR NDB_STTORRY ALL BLOCK HAVE FINISHED // THEIR LOCAL CONNECTIONs SUCESSFULLY // AND THEN WE CAN SEND APPL_STARTREG TO INFORM QMGR THAT WE ARE READY TO // SET UP DISTRIBUTED CONNECTIONS. /*--------------------------------------------------------------*/ // THIS IS NDB START PHASE 3. /*--------------------------------------------------------------*/ /*******************************/ /* STTOR */ /*******************************/ void Ndbcntr::startPhase3Lab(Signal* signal) { ph3ALab(signal); return; }//Ndbcntr::startPhase3Lab() /*******************************/ /* NDB_STTORRY */ /*******************************/ void Ndbcntr::ph3ALab(Signal* signal) { if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if sendSttorry(signal); return; }//Ndbcntr::ph3ALab() /* 4.5 START PHASE 4 */ /*###########################################################################*/ // WAIT FOR ALL NODES IN CLUSTER TO CHANGE STATE INTO ZSTART , // APPL_CHANGEREP IS ALWAYS SENT WHEN SOMEONE HAVE // CHANGED THEIR STATE. APPL_STARTCONF INDICATES THAT ALL NODES ARE IN START // STATE SEND NDB_STARTREQ TO DIH AND THEN WAIT FOR NDB_STARTCONF /*---------------------------------------------------------------------------*/ /*******************************/ /* STTOR */ /*******************************/ void Ndbcntr::startPhase4Lab(Signal* signal) { ph4ALab(signal); }//Ndbcntr::startPhase4Lab() void Ndbcntr::ph4ALab(Signal* signal) { ph4BLab(signal); return; }//Ndbcntr::ph4ALab() /*******************************/ /* NDB_STTORRY */ /*******************************/ void Ndbcntr::ph4BLab(Signal* signal) { /*--------------------------------------*/ /* CASE: CSTART_PHASE = ZSTART_PHASE_4 */ /*--------------------------------------*/ if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); sendSttorry(signal); return; }//if waitpoint41Lab(signal); return; }//Ndbcntr::ph4BLab() void Ndbcntr::waitpoint41Lab(Signal* signal) { if (getOwnNodeId() == cmasterNodeId) { jam(); /*--------------------------------------*/ /* MASTER WAITS UNTIL ALL SLAVES HAS */ /* SENT THE REPORTS */ /*--------------------------------------*/ 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 // DATA IT USES THAT DATA TO SET UP WHICH FRAGMENTS THAT ARE TO START AND // WHERE THEY ARE TO START. THEN // IT SETS UP THE FRAGMENTS AND RECOVERS THEM BY: // 1) READING A LOCAL CHECKPOINT FROM DISK. // 2) EXECUTING THE UNDO LOG ON INDEX AND DATA. // 3) EXECUTING THE FRAGMENT REDO LOG FROM ONE OR SEVERAL NODES TO // RESTORE THE RESTART CONFIGURATION OF DATA IN NDB CLUSTER. /*---------------------------------------------------------------------------*/ signal->theData[0] = reference(); signal->theData[1] = ctypeOfStart; sendSignal(DBDIH_REF, GSN_NDB_STARTREQ, signal, 2, JBB); }//if } else { jam(); /*--------------------------------------*/ /* SLAVE NODES WILL PASS HERE ONCE AND */ /* SEND A WAITPOINT REPORT TO MASTER. */ /* SLAVES WONT DO ANYTHING UNTIL THEY */ /* RECEIVE A WAIT REPORT FROM THE MASTER*/ /*--------------------------------------*/ signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_4_1; sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); }//if return; }//Ndbcntr::waitpoint41Lab() void Ndbcntr::waitpoint42To(Signal* signal) { jam(); /** * This is a ugly hack * To "easy" enable TO during SR * a better solution would be to move "all" start handling * from DIH to cntr...which knows what's going on */ cdihStartType = NodeState::ST_SYSTEM_RESTART; ctypeOfStart = NodeState::ST_NODE_RESTART; /** * This is immensely ugly...but makes TUX work (yuck) */ { NodeStateRep* rep = (NodeStateRep*)signal->getDataPtrSend(); rep->nodeState = getNodeState(); rep->nodeState.masterNodeId = cmasterNodeId; rep->nodeState.setNodeGroup(c_nodeGroup); rep->nodeState.starting.restartType = NodeState::ST_NODE_RESTART; sendSignal(DBTUX_REF, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength, JBB); } /** * We were forced to perform TO */ StartCopyReq* req = (StartCopyReq*)signal->getDataPtrSend(); req->senderRef = reference(); req->senderData = RNIL; req->flags = StartCopyReq::WAIT_LCP; req->startingNodeId = getOwnNodeId(); sendSignal(DBDIH_REF, GSN_START_COPYREQ, signal, StartCopyReq::SignalLength, JBB); } void Ndbcntr::execSTART_COPYREF(Signal* signal) { } void Ndbcntr::execSTART_COPYCONF(Signal* signal) { sendSttorry(signal); } /*******************************/ /* NDB_STARTCONF */ /*******************************/ void Ndbcntr::execNDB_STARTCONF(Signal* signal) { jamEntry(); NdbNodeBitmask tmp; if (signal->getLength() >= 1 + NdbNodeBitmask::Size) { jam(); tmp.assign(NdbNodeBitmask::Size, signal->theData+1); if (!c_start.m_starting.equal(tmp)) { /** * Some nodes has been "excluded" from SR */ char buf0[100], buf1[100]; ndbout_c("execNDB_STARTCONF: changing from %s to %s", c_start.m_starting.getText(buf0), tmp.getText(buf1)); NdbNodeBitmask waiting = c_start.m_starting; waiting.bitANDC(tmp); c_start.m_waiting.bitOR(waiting); c_start.m_waitTO.bitOR(waiting); c_start.m_starting.assign(tmp); cnoStartNodes = c_start.m_starting.count(); } } NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_4_2; c_start.m_starting.copyto(NdbNodeBitmask::Size, signal->theData+2); sendSignal(rg, GSN_CNTR_WAITREP, signal, 2 + NdbNodeBitmask::Size, JBB); return; }//Ndbcntr::execNDB_STARTCONF() /* 4.6 START PHASE 5 */ /*###########################################################################*/ // SEND APPL_RUN TO THE QMGR IN THIS BLOCK // SEND NDB_STTOR ALL BLOCKS ACC, DICT, DIH, LQH, TC AND TUP THEN WAIT FOR // THEIR NDB_STTORRY /*---------------------------------------------------------------------------*/ /*******************************/ /* STTOR */ /*******************************/ void Ndbcntr::startPhase5Lab(Signal* signal) { ph5ALab(signal); return; }//Ndbcntr::startPhase5Lab() /*******************************/ /* NDB_STTORRY */ /*******************************/ /*---------------------------------------------------------------------------*/ // THIS IS NDB START PHASE 5. /*---------------------------------------------------------------------------*/ // IN THIS START PHASE TUP INITIALISES DISK FILES FOR DISK STORAGE IF INITIAL // START. DIH WILL START UP // THE GLOBAL CHECKPOINT PROTOCOL AND WILL CONCLUDE ANY UNFINISHED TAKE OVERS // THAT STARTED BEFORE THE SYSTEM CRASH. /*---------------------------------------------------------------------------*/ void Ndbcntr::ph5ALab(Signal* signal) { if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if cstartPhase = cstartPhase + 1; cinternalStartphase = cstartPhase - 1; if (getOwnNodeId() == cmasterNodeId) { switch(ctypeOfStart){ case NodeState::ST_INITIAL_START: jam(); /*--------------------------------------*/ /* MASTER CNTR IS RESPONSIBLE FOR */ /* CREATING SYSTEM TABLES */ /*--------------------------------------*/ beginSchemaTransLab(signal); return; case NodeState::ST_SYSTEM_RESTART: jam(); waitpoint52Lab(signal); return; case NodeState::ST_NODE_RESTART: case NodeState::ST_INITIAL_NODE_RESTART: jam(); break; case NodeState::ST_ILLEGAL_TYPE: jam(); break; } ndbrequire(false); } /** * Not master */ NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend(); switch(ctypeOfStart){ case NodeState::ST_NODE_RESTART: case NodeState::ST_INITIAL_NODE_RESTART: jam(); /*----------------------------------------------------------------------*/ // SEND NDB START PHASE 5 IN NODE RESTARTS TO COPY DATA TO THE NEWLY // STARTED NODE. /*----------------------------------------------------------------------*/ req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = cdihStartType; req->masterNodeId = cmasterNodeId; //#define TRACE_STTOR #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase); #endif sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal, NdbSttor::SignalLength, JBB); return; case NodeState::ST_INITIAL_START: case NodeState::ST_SYSTEM_RESTART: jam(); /*--------------------------------------*/ /* DURING SYSTEMRESTART AND INITALSTART:*/ /* SLAVE NODES WILL PASS HERE ONCE AND */ /* SEND A WAITPOINT REPORT TO MASTER. */ /* SLAVES WONT DO ANYTHING UNTIL THEY */ /* RECEIVE A WAIT REPORT FROM THE MASTER*/ /* WHEN THE MASTER HAS FINISHED HIS WORK*/ /*--------------------------------------*/ signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_5_2; sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); return; default: ndbrequire(false); } }//Ndbcntr::ph5ALab() void Ndbcntr::waitpoint52Lab(Signal* signal) { cnoWaitrep = cnoWaitrep + 1; /*---------------------------------------------------------------------------*/ // THIS WAITING POINT IS ONLY USED BY A MASTER NODE. WE WILL EXECUTE NDB START // PHASE 5 FOR DIH IN THE // MASTER. THIS WILL START UP LOCAL CHECKPOINTS AND WILL ALSO CONCLUDE ANY // UNFINISHED LOCAL CHECKPOINTS // BEFORE THE SYSTEM CRASH. THIS WILL ENSURE THAT WE ALWAYS RESTART FROM A // WELL KNOWN STATE. /*---------------------------------------------------------------------------*/ /*--------------------------------------*/ /* MASTER WAITS UNTIL HE RECEIVED WAIT */ /* REPORTS FROM ALL SLAVE CNTR */ /*--------------------------------------*/ if (cnoWaitrep == cnoStartNodes) { jam(); cnoWaitrep = 0; NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend(); req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = cdihStartType; req->masterNodeId = cmasterNodeId; #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase); #endif sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal, NdbSttor::SignalLength, JBB); }//if return; }//Ndbcntr::waitpoint52Lab() /*******************************/ /* NDB_STTORRY */ /*******************************/ void Ndbcntr::ph6ALab(Signal* signal) { if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); waitpoint51Lab(signal); return; }//if NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); rg.m_nodes.clear(getOwnNodeId()); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_5_1; sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); waitpoint51Lab(signal); return; }//Ndbcntr::ph6ALab() void Ndbcntr::waitpoint51Lab(Signal* signal) { cstartPhase = cstartPhase + 1; /*---------------------------------------------------------------------------*/ // A FINAL STEP IS NOW TO SEND NDB_STTOR TO TC. THIS MAKES IT POSSIBLE TO // CONNECT TO TC FOR APPLICATIONS. // THIS IS NDB START PHASE 6 WHICH IS FOR ALL BLOCKS IN ALL NODES. /*---------------------------------------------------------------------------*/ cinternalStartphase = cstartPhase - 1; cndbBlocksCount = 0; ph6BLab(signal); return; }//Ndbcntr::waitpoint51Lab() void Ndbcntr::ph6BLab(Signal* signal) { // c_missra.currentStartPhase - cstartPhase - cinternalStartphase = // 5 - 7 - 6 if (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; }//if if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); sendSttorry(signal); return; } waitpoint61Lab(signal); } void Ndbcntr::waitpoint61Lab(Signal* signal) { if (getOwnNodeId() == cmasterNodeId) { jam(); cnoWaitrep6++; if (cnoWaitrep6 == cnoStartNodes) { jam(); NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); rg.m_nodes.clear(getOwnNodeId()); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_6_2; sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); sendSttorry(signal); } } else { jam(); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_6_1; sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); } } // Start phase 8 (internal 7) void Ndbcntr::startPhase8Lab(Signal* signal) { cinternalStartphase = cstartPhase - 1; cndbBlocksCount = 0; ph7ALab(signal); } void Ndbcntr::ph7ALab(Signal* signal) { while (cndbBlocksCount < ZNO_NDB_BLOCKS) { jam(); sendNdbSttor(signal); return; } if ((ctypeOfStart == NodeState::ST_NODE_RESTART) || (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); sendSttorry(signal); return; } waitpoint71Lab(signal); } void Ndbcntr::waitpoint71Lab(Signal* signal) { if (getOwnNodeId() == cmasterNodeId) { jam(); cnoWaitrep7++; if (cnoWaitrep7 == cnoStartNodes) { jam(); NodeReceiverGroup rg(NDBCNTR, c_start.m_starting); rg.m_nodes.clear(getOwnNodeId()); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_7_2; sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB); sendSttorry(signal); } } else { jam(); signal->theData[0] = getOwnNodeId(); signal->theData[1] = CntrWaitRep::ZWAITPOINT_7_1; sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB); } } // Start phase 9 (internal 8) void Ndbcntr::startPhase9Lab(Signal* signal) { cinternalStartphase = cstartPhase - 1; cndbBlocksCount = 0; ph8ALab(signal); } void Ndbcntr::ph8ALab(Signal* signal) { /*---------------------------------------------------------------------------*/ // NODES WHICH PERFORM A NODE RESTART NEEDS TO GET THE DYNAMIC ID'S // OF THE OTHER NODES HERE. /*---------------------------------------------------------------------------*/ sendSttorry(signal); resetStartVariables(signal); return; }//Ndbcntr::ph8BLab() bool Ndbcntr::wait_sp(Signal* signal, Uint32 sp) { if (sp <= 2) return false; switch(ctypeOfStart){ case NodeState::ST_SYSTEM_RESTART: case NodeState::ST_INITIAL_START: /** * synchronized... */ break; default: return false; } if (!ndb_wait_sp(getNodeInfo(cmasterNodeId).m_version)) return false; CntrWaitRep* rep = (CntrWaitRep*)signal->getDataPtrSend(); rep->nodeId = getOwnNodeId(); rep->waitPoint = RNIL; rep->request = CntrWaitRep::WaitFor; rep->sp = sp; sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, CntrWaitRep::SignalLength, JBB); return true; // wait } void Ndbcntr::wait_sp_rep(Signal* signal) { CntrWaitRep rep = *(CntrWaitRep*)signal->getDataPtrSend(); switch(rep.request){ case CntrWaitRep::WaitFor: jam(); ndbrequire(cmasterNodeId == getOwnNodeId()); break; case CntrWaitRep::Grant: jam(); /** * We're allowed to proceed */ c_missra.sendNextSTTOR(signal); return; } c_start.m_wait_sp[rep.nodeId] = rep.sp; /** * Check if we should allow someone to start... */ Uint32 node = c_start.m_starting.find(0); ndbrequire(node < NDB_ARRAY_SIZE(c_start.m_wait_sp)); Uint32 min = c_start.m_wait_sp[node]; for (; node != NdbNodeBitmask::NotFound; node = c_start.m_starting.find(node + 1)) { if (!ndb_wait_sp(getNodeInfo(node).m_version)) continue; if (c_start.m_wait_sp[node] < min) { min = c_start.m_wait_sp[node]; } } if (min == 0) { /** * wait for more */ return; } NdbNodeBitmask grantnodes; node = c_start.m_starting.find(0); for (; node != NdbNodeBitmask::NotFound; node = c_start.m_starting.find(node + 1)) { if (!ndb_wait_sp(getNodeInfo(node).m_version)) continue; if (c_start.m_wait_sp[node] == min) { grantnodes.set(node); c_start.m_wait_sp[node] = 0; } } NodeReceiverGroup rg(NDBCNTR, grantnodes); CntrWaitRep * conf = (CntrWaitRep*)signal->getDataPtrSend(); conf->nodeId = getOwnNodeId(); conf->waitPoint = RNIL; conf->request = CntrWaitRep::Grant; conf->sp = min; sendSignal(rg, GSN_CNTR_WAITREP, signal, CntrWaitRep::SignalLength, JBB); } /*******************************/ /* CNTR_WAITREP */ /*******************************/ void Ndbcntr::execCNTR_WAITREP(Signal* signal) { jamEntry(); CntrWaitRep* rep = (CntrWaitRep*)signal->getDataPtr(); Uint32 twaitPoint = rep->waitPoint; switch (twaitPoint) { case CntrWaitRep::ZWAITPOINT_4_1: jam(); waitpoint41Lab(signal); break; case CntrWaitRep::ZWAITPOINT_4_2: jam(); c_start.m_starting.assign(NdbNodeBitmask::Size, signal->theData + 2); sendSttorry(signal); break; case CntrWaitRep::ZWAITPOINT_5_1: jam(); waitpoint51Lab(signal); break; case CntrWaitRep::ZWAITPOINT_5_2: jam(); waitpoint52Lab(signal); break; case CntrWaitRep::ZWAITPOINT_6_1: jam(); waitpoint61Lab(signal); break; case CntrWaitRep::ZWAITPOINT_6_2: jam(); sendSttorry(signal); break; case CntrWaitRep::ZWAITPOINT_7_1: jam(); waitpoint71Lab(signal); break; case CntrWaitRep::ZWAITPOINT_7_2: jam(); sendSttorry(signal); break; case CntrWaitRep::ZWAITPOINT_4_2_TO: jam(); waitpoint42To(signal); break; case RNIL: ndbrequire(signal->getLength() >= CntrWaitRep::SignalLength); wait_sp_rep(signal); return; default: jam(); systemErrorLab(signal, __LINE__); break; }//switch }//Ndbcntr::execCNTR_WAITREP() /*******************************/ /* NODE_FAILREP */ /*******************************/ void Ndbcntr::execNODE_FAILREP(Signal* signal) { jamEntry(); if (ERROR_INSERTED(1001)) { sendSignalWithDelay(reference(), GSN_NODE_FAILREP, signal, 100, signal->getLength()); return; } 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(); 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_start.m_waitTO.bitANDC(allFailed); c_clusterNodes.bitANDC(allFailed); c_startedNodes.bitANDC(allFailed); const NodeState & st = getNodeState(); if(st.startLevel == st.SL_STARTING){ jam(); const Uint32 phase = st.starting.startPhase; const bool tStartConf = (phase > 2) || (phase == 2 && cndbBlocksCount > 0); if(tMasterFailed){ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, "Unhandled node failure during restart"); } if(tStartConf && tStarting){ // One of other starting nodes has crashed... progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, "Unhandled node failure of starting node during restart"); } if(tStartConf && tStarted){ // One of other started nodes has crashed... progError(__LINE__, NDBD_EXIT_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 return; } ndbrequire(!allFailed.get(getOwnNodeId())); NodeFailRep * rep = (NodeFailRep *)&signal->theData[0]; rep->masterNodeId = cmasterNodeId; sendSignal(DBTC_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBLQH_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBDIH_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBDICT_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(QMGR_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBUTIL_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBTUP_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(TSMAN_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(LGMAN_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); sendSignal(DBSPJ_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); if (c_stopRec.stopReq.senderRef) { jam(); switch(c_stopRec.m_state){ case StopRecord::SR_WAIT_NODE_FAILURES: { jam(); NdbNodeBitmask tmp; tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); tmp.bitANDC(allFailed); tmp.copyto(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); if (tmp.isclear()) { jam(); if (c_stopRec.stopReq.senderRef != RNIL) { jam(); StopConf * const stopConf = (StopConf *)&signal->theData[0]; stopConf->senderData = c_stopRec.stopReq.senderData; stopConf->nodeState = (Uint32) NodeState::SL_SINGLEUSER; sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_CONF, signal, StopConf::SignalLength, JBB); } c_stopRec.stopReq.senderRef = 0; WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = StopRecord::SR_UNBLOCK_GCP_START_GCP; req->requestType = WaitGCPReq::UnblockStartGcp; sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBA); } break; } case StopRecord::SR_QMGR_STOP_REQ: { NdbNodeBitmask tmp; tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); tmp.bitANDC(allFailed); if (tmp.isclear()) { Uint32 nodeId = allFailed.find(0); tmp.set(nodeId); StopConf* conf = (StopConf*)signal->getDataPtrSend(); conf->senderData = c_stopRec.stopReq.senderData; conf->nodeId = nodeId; sendSignal(reference(), GSN_STOP_CONF, signal, StopConf::SignalLength, JBB); } tmp.copyto(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); break; } case StopRecord::SR_BLOCK_GCP_START_GCP: case StopRecord::SR_WAIT_COMPLETE_GCP: case StopRecord::SR_UNBLOCK_GCP_START_GCP: case StopRecord::SR_CLUSTER_SHUTDOWN: break; } } signal->theData[0] = NDB_LE_NODE_FAILREP; signal->theData[2] = 0; Uint32 nodeId = 0; while(!allFailed.isclear()){ nodeId = allFailed.find(nodeId + 1); allFailed.clear(nodeId); signal->theData[1] = nodeId; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); }//for return; }//Ndbcntr::execNODE_FAILREP() /*******************************/ /* READ_NODESREQ */ /*******************************/ void Ndbcntr::execREAD_NODESREQ(Signal* signal) { jamEntry(); /*----------------------------------------------------------------------*/ // ANY BLOCK MAY SEND A REQUEST ABOUT NDB NODES AND VERSIONS IN THE // SYSTEM. THIS REQUEST CAN ONLY BE HANDLED IN // ABSOLUTE STARTPHASE 3 OR LATER /*----------------------------------------------------------------------*/ BlockReference TuserBlockref = signal->theData[0]; ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0]; /** * 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()); } 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 (m_cntr_start_conf) { jam(); sendSignal(TuserBlockref, GSN_READ_NODESCONF, signal, ReadNodesConf::SignalLength, JBB); } else { jam(); signal->theData[0] = ZNOT_AVAILABLE; sendSignal(TuserBlockref, GSN_READ_NODESREF, signal, 1, JBB); }//if }//Ndbcntr::execREAD_NODESREQ() /*----------------------------------------------------------------------*/ // SENDS APPL_ERROR TO QMGR AND THEN SET A POINTER OUT OF BOUNDS /*----------------------------------------------------------------------*/ void Ndbcntr::systemErrorLab(Signal* signal, int line) { progError(line, NDBD_EXIT_NDBREQUIRE); /* BUG INSERTION */ return; }//Ndbcntr::systemErrorLab() /*###########################################################################*/ /* CNTR MASTER CREATES AND INITIALIZES A SYSTEMTABLE AT INITIALSTART */ /* |-2048| # 1 00000001 | */ /* | : | : | */ /* | -1 | # 1 00000001 | */ /* | 1 | 0 | tupleid sequence now created on first use */ /* | : | : | v */ /* | 2048| 0 | v */ /*---------------------------------------------------------------------------*/ void Ndbcntr::beginSchemaTransLab(Signal* signal) { c_schemaTransId = reference(); SchemaTransBeginReq* req = (SchemaTransBeginReq*)signal->getDataPtrSend(); req->clientRef = reference(); req->transId = c_schemaTransId; req->requestInfo = 0; sendSignal(DBDICT_REF, GSN_SCHEMA_TRANS_BEGIN_REQ, signal, SchemaTransBeginReq::SignalLength, JBB); } void Ndbcntr::execSCHEMA_TRANS_BEGIN_CONF(Signal* signal) { const SchemaTransBeginConf* conf = (SchemaTransBeginConf*)signal->getDataPtr(); ndbrequire(conf->transId == c_schemaTransId); c_schemaTransKey = conf->transKey; createHashMap(signal, 0); } void Ndbcntr::execSCHEMA_TRANS_BEGIN_REF(Signal* signal) { ndbrequire(false); } void Ndbcntr::createHashMap(Signal* signal, Uint32 idx) { CreateHashMapReq* const req = (CreateHashMapReq*)signal->getDataPtrSend(); req->clientRef = reference(); req->clientData = idx; req->requestInfo = 0; req->transId = c_schemaTransId; req->transKey = c_schemaTransKey; req->buckets = 240; req->fragments = 0; sendSignal(DBDICT_REF, GSN_CREATE_HASH_MAP_REQ, signal, CreateHashMapReq::SignalLength, JBB); } void Ndbcntr::execCREATE_HASH_MAP_REF(Signal* signal) { jamEntry(); ndbrequire(false); } void Ndbcntr::execCREATE_HASH_MAP_CONF(Signal* signal) { jamEntry(); CreateHashMapConf* conf = (CreateHashMapConf*)signal->getDataPtrSend(); if (conf->senderData == 0) { jam(); c_hashMapId = conf->objectId; c_hashMapVersion = conf->objectVersion; } createSystableLab(signal, 0); } void Ndbcntr::endSchemaTransLab(Signal* signal) { SchemaTransEndReq* req = (SchemaTransEndReq*)signal->getDataPtrSend(); req->clientRef = reference(); req->transId = c_schemaTransId; req->requestInfo = 0; req->transKey = c_schemaTransKey; req->flags = 0; sendSignal(DBDICT_REF, GSN_SCHEMA_TRANS_END_REQ, signal, SchemaTransEndReq::SignalLength, JBB); } void Ndbcntr::execSCHEMA_TRANS_END_CONF(Signal* signal) { c_schemaTransId = 0; c_schemaTransKey = RNIL; startInsertTransactions(signal); } void Ndbcntr::execSCHEMA_TRANS_END_REF(Signal* signal) { jamEntry(); SchemaTransEndRef * ref = (SchemaTransEndRef*)signal->getDataPtr(); char buf[256]; BaseString::snprintf(buf, sizeof(buf), "Failed to commit schema trans, err: %u", ref->errorCode); progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf); ndbrequire(false); } void Ndbcntr::createDDObjects(Signal * signal, unsigned index) { const ndb_mgm_configuration_iterator * p = m_ctx.m_config.getOwnConfigIterator(); ndbrequire(p != 0); Uint32 propPage[256]; LinearWriter w(propPage, 256); const ddentry* entry = &f_dd[index]; switch(entry->type){ case DictTabInfo::LogfileGroup: case DictTabInfo::Tablespace: { jam(); DictFilegroupInfo::Filegroup fg; fg.init(); BaseString::snprintf(fg.FilegroupName, sizeof(fg.FilegroupName), "%s", entry->name); fg.FilegroupType = entry->type; if (entry->type == DictTabInfo::LogfileGroup) { jam(); fg.LF_UndoBufferSize = Uint32(entry->size); } else { jam(); fg.TS_ExtentSize = Uint32(entry->size); fg.TS_LogfileGroupId = RNIL; fg.TS_LogfileGroupVersion = RNIL; } SimpleProperties::UnpackStatus s; s = SimpleProperties::pack(w, &fg, DictFilegroupInfo::Mapping, DictFilegroupInfo::MappingSize, true); Uint32 length = w.getWordsUsed(); LinearSectionPtr ptr[3]; ptr[0].p = &propPage[0]; ptr[0].sz = length; CreateFilegroupReq * req = (CreateFilegroupReq*)signal->getDataPtrSend(); req->senderRef = reference(); req->senderData = index; req->objType = entry->type; req->transId = c_schemaTransId; req->transKey = c_schemaTransKey; req->requestInfo = 0; sendSignal(DBDICT_REF, GSN_CREATE_FILEGROUP_REQ, signal, CreateFilegroupReq::SignalLength, JBB, ptr, 1); return; } case DictTabInfo::Undofile: case DictTabInfo::Datafile: { jam(); Uint32 propPage[256]; LinearWriter w(propPage, 256); DictFilegroupInfo::File f; f.init(); BaseString::snprintf(f.FileName, sizeof(f.FileName), "%s", entry->name); f.FileType = entry->type; f.FilegroupId = RNIL; f.FilegroupVersion = RNIL; f.FileSizeHi = Uint32(entry->size >> 32); f.FileSizeLo = Uint32(entry->size); SimpleProperties::UnpackStatus s; s = SimpleProperties::pack(w, &f, DictFilegroupInfo::FileMapping, DictFilegroupInfo::FileMappingSize, true); Uint32 length = w.getWordsUsed(); LinearSectionPtr ptr[3]; ptr[0].p = &propPage[0]; ptr[0].sz = length; CreateFileReq * req = (CreateFileReq*)signal->getDataPtrSend(); req->senderRef = reference(); req->senderData = index; req->objType = entry->type; req->transId = c_schemaTransId; req->transKey = c_schemaTransKey; req->requestInfo = CreateFileReq::ForceCreateFile; sendSignal(DBDICT_REF, GSN_CREATE_FILE_REQ, signal, CreateFileReq::SignalLength, JBB, ptr, 1); return; } default: break; } endSchemaTransLab(signal); } void Ndbcntr::execCREATE_FILEGROUP_REF(Signal* signal) { jamEntry(); CreateFilegroupRef* ref = (CreateFilegroupRef*)signal->getDataPtr(); char buf[1024]; const ddentry* entry = &f_dd[ref->senderData]; if (entry->type == DictTabInfo::LogfileGroup) { BaseString::snprintf(buf, sizeof(buf), "create logfilegroup err %u", ref->errorCode); } else if (entry->type == DictTabInfo::Tablespace) { BaseString::snprintf(buf, sizeof(buf), "create tablespace err %u", ref->errorCode); } progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf); } void Ndbcntr::execCREATE_FILEGROUP_CONF(Signal* signal) { jamEntry(); CreateFilegroupConf* conf = (CreateFilegroupConf*)signal->getDataPtr(); createDDObjects(signal, conf->senderData + 1); } void Ndbcntr::execCREATE_FILE_REF(Signal* signal) { jamEntry(); CreateFileRef* ref = (CreateFileRef*)signal->getDataPtr(); char buf[1024]; const ddentry* entry = &f_dd[ref->senderData]; if (entry->type == DictTabInfo::Undofile) { BaseString::snprintf(buf, sizeof(buf), "create undofile %s err %u", entry->name, ref->errorCode); } else if (entry->type == DictTabInfo::Datafile) { BaseString::snprintf(buf, sizeof(buf), "create datafile %s err %u", entry->name, ref->errorCode); } progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf); } void Ndbcntr::execCREATE_FILE_CONF(Signal* signal) { jamEntry(); CreateFileConf* conf = (CreateFileConf*)signal->getDataPtr(); createDDObjects(signal, conf->senderData + 1); } void Ndbcntr::createSystableLab(Signal* signal, unsigned index) { if (index >= g_sysTableCount) { ndbassert(index == g_sysTableCount); createDDObjects(signal, 0); return; } const SysTable& table = *g_sysTableList[index]; Uint32 propPage[256]; LinearWriter w(propPage, 256); // XXX remove commented-out lines later w.first(); w.add(DictTabInfo::TableName, table.name); w.add(DictTabInfo::TableLoggedFlag, table.tableLoggedFlag); //w.add(DictTabInfo::TableKValue, 6); //w.add(DictTabInfo::MinLoadFactor, 70); //w.add(DictTabInfo::MaxLoadFactor, 80); w.add(DictTabInfo::FragmentTypeVal, (Uint32)table.fragmentType); //w.add(DictTabInfo::NoOfKeyAttr, 1); w.add(DictTabInfo::NoOfAttributes, (Uint32)table.columnCount); //w.add(DictTabInfo::NoOfNullable, (Uint32)0); //w.add(DictTabInfo::NoOfVariable, (Uint32)0); //w.add(DictTabInfo::KeyLength, 1); w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType); w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE); w.add(DictTabInfo::HashMapObjectId, c_hashMapId); w.add(DictTabInfo::HashMapVersion, c_hashMapVersion); for (unsigned i = 0; i < table.columnCount; i++) { const SysColumn& column = table.columnList[i]; ndbassert(column.pos == i); w.add(DictTabInfo::AttributeName, column.name); w.add(DictTabInfo::AttributeId, (Uint32)i); w.add(DictTabInfo::AttributeKeyFlag, (Uint32)column.keyFlag); w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_MEMORY); switch(column.type){ case DictTabInfo::ExtVarbinary: jam(); w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_SHORT_VAR); break; case DictTabInfo::ExtLongvarbinary: jam(); w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_MEDIUM_VAR); break; default: jam(); w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_FIXED); break; } w.add(DictTabInfo::AttributeNullableFlag, (Uint32)column.nullable); w.add(DictTabInfo::AttributeExtType, (Uint32)column.type); w.add(DictTabInfo::AttributeExtLength, (Uint32)column.length); w.add(DictTabInfo::AttributeEnd, (Uint32)true); } w.add(DictTabInfo::TableEnd, (Uint32)true); Uint32 length = w.getWordsUsed(); LinearSectionPtr ptr[3]; ptr[0].p = &propPage[0]; ptr[0].sz = length; CreateTableReq* const req = (CreateTableReq*)signal->getDataPtrSend(); req->clientRef = reference(); req->clientData = index; req->requestInfo = 0; req->transId = c_schemaTransId; req->transKey = c_schemaTransKey; sendSignal(DBDICT_REF, GSN_CREATE_TABLE_REQ, signal, CreateTableReq::SignalLength, JBB, ptr, 1); return; }//Ndbcntr::createSystableLab() void Ndbcntr::execCREATE_TABLE_REF(Signal* signal) { jamEntry(); progError(__LINE__,NDBD_EXIT_NDBREQUIRE, "CREATE_TABLE_REF"); return; }//Ndbcntr::execDICTTABREF() void Ndbcntr::execCREATE_TABLE_CONF(Signal* signal) { jamEntry(); const CreateTableConf* conf = (const CreateTableConf*)signal->getDataPtr(); //csystabId = conf->tableId; ndbrequire(conf->transId == c_schemaTransId); ndbrequire(conf->senderData < g_sysTableCount); const SysTable& table = *g_sysTableList[conf->senderData]; table.tableId = conf->tableId; table.tableVersion = conf->tableVersion; createSystableLab(signal, conf->senderData + 1); //startInsertTransactions(signal); return; }//Ndbcntr::execDICTTABCONF() /*******************************/ /* DICTRELEASECONF */ /*******************************/ void Ndbcntr::startInsertTransactions(Signal* signal) { jamEntry(); ckey = 1; ctransidPhase = ZTRUE; signal->theData[0] = 0; signal->theData[1] = reference(); sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB); return; }//Ndbcntr::startInsertTransactions() /*******************************/ /* TCSEIZECONF */ /*******************************/ void Ndbcntr::execTCSEIZECONF(Signal* signal) { jamEntry(); ctcConnectionP = signal->theData[1]; ctcReference = signal->theData[2]; crSystab7Lab(signal); return; }//Ndbcntr::execTCSEIZECONF() const unsigned int RowsPerCommit = 16; void Ndbcntr::crSystab7Lab(Signal* signal) { UintR tkey; UintR Tmp; TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0]; UintR reqInfo_Start = 0; tcKeyReq->setOperationType(reqInfo_Start, ZINSERT); // Insert tcKeyReq->setKeyLength (reqInfo_Start, 1); tcKeyReq->setAIInTcKeyReq (reqInfo_Start, 5); tcKeyReq->setAbortOption (reqInfo_Start, TcKeyReq::AbortOnError); /* KEY LENGTH = 1, ATTRINFO LENGTH IN TCKEYREQ = 5 */ cresponses = 0; const UintR guard0 = ckey + (RowsPerCommit - 1); for (Tmp = ckey; Tmp <= guard0; Tmp++) { UintR reqInfo = reqInfo_Start; if (Tmp == ckey) { // First iteration, Set start flag jam(); tcKeyReq->setStartFlag(reqInfo, 1); } //if if (Tmp == guard0) { // Last iteration, Set commit flag jam(); tcKeyReq->setCommitFlag(reqInfo, 1); tcKeyReq->setExecuteFlag(reqInfo, 1); } //if if (ctransidPhase == ZTRUE) { jam(); tkey = 0; tkey = tkey - Tmp; } else { jam(); tkey = Tmp; }//if tcKeyReq->apiConnectPtr = ctcConnectionP; tcKeyReq->attrLen = 5; tcKeyReq->tableId = g_sysTable_SYSTAB_0.tableId; tcKeyReq->requestInfo = reqInfo; tcKeyReq->tableSchemaVersion = g_sysTable_SYSTAB_0.tableVersion; tcKeyReq->transId1 = 0; tcKeyReq->transId2 = ckey; //------------------------------------------------------------- // There is no optional part in this TCKEYREQ. There is one // key word and five ATTRINFO words. //------------------------------------------------------------- Uint32* tKeyDataPtr = &tcKeyReq->scanInfo; Uint32* tAIDataPtr = &tKeyDataPtr[1]; tKeyDataPtr[0] = tkey; AttributeHeader::init(&tAIDataPtr[0], 0, 1 << 2); tAIDataPtr[1] = tkey; AttributeHeader::init(&tAIDataPtr[2], 1, 2 << 2); tAIDataPtr[3] = (tkey << 16); tAIDataPtr[4] = 1; sendSignal(ctcReference, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength + 6, JBB); }//for ckey = ckey + RowsPerCommit; return; }//Ndbcntr::crSystab7Lab() /*******************************/ /* TCKEYCONF09 */ /*******************************/ void Ndbcntr::execTCKEYCONF(Signal* signal) { const TcKeyConf * const keyConf = (TcKeyConf *)&signal->theData[0]; jamEntry(); cgciSystab = keyConf->gci_hi; UintR confInfo = keyConf->confInfo; if (TcKeyConf::getMarkerFlag(confInfo)){ Uint32 transId1 = keyConf->transId1; Uint32 transId2 = keyConf->transId2; signal->theData[0] = transId1; signal->theData[1] = transId2; sendSignal(ctcReference, GSN_TC_COMMIT_ACK, signal, 2, JBB); }//if cresponses = cresponses + TcKeyConf::getNoOfOperations(confInfo); if (TcKeyConf::getCommitFlag(confInfo)){ jam(); ndbrequire(cresponses == RowsPerCommit); crSystab8Lab(signal); return; } return; }//Ndbcntr::tckeyConfLab() void Ndbcntr::crSystab8Lab(Signal* signal) { if (ckey < ZSIZE_SYSTAB) { jam(); crSystab7Lab(signal); return; } else if (ctransidPhase == ZTRUE) { jam(); ckey = 1; ctransidPhase = ZFALSE; // skip 2nd loop - tupleid sequence now created on first use }//if signal->theData[0] = ctcConnectionP; signal->theData[1] = reference(); signal->theData[2] = 0; sendSignal(ctcReference, GSN_TCRELEASEREQ, signal, 2, JBB); return; }//Ndbcntr::crSystab8Lab() /*******************************/ /* TCRELEASECONF */ /*******************************/ void Ndbcntr::execTCRELEASECONF(Signal* signal) { jamEntry(); waitpoint52Lab(signal); return; }//Ndbcntr::execTCRELEASECONF() void Ndbcntr::crSystab9Lab(Signal* signal) { signal->theData[0] = 0; // user ptr signal->theData[1] = reference(); signal->theData[2] = 0; sendSignalWithDelay(DBDIH_REF, GSN_GETGCIREQ, signal, 100, 3); return; }//Ndbcntr::crSystab9Lab() /*******************************/ /* GETGCICONF */ /*******************************/ void Ndbcntr::execGETGCICONF(Signal* signal) { jamEntry(); #ifndef NO_GCP if (signal->theData[1] < cgciSystab) { jam(); /*--------------------------------------*/ /* MAKE SURE THAT THE SYSTABLE IS */ /* NOW SAFE ON DISK */ /*--------------------------------------*/ crSystab9Lab(signal); return; }//if #endif waitpoint52Lab(signal); return; }//Ndbcntr::execGETGCICONF() void Ndbcntr::execTCKEYREF(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execTCKEYREF() void Ndbcntr::execTCROLLBACKREP(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execTCROLLBACKREP() void Ndbcntr::execTCRELEASEREF(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execTCRELEASEREF() void Ndbcntr::execTCSEIZEREF(Signal* signal) { jamEntry(); systemErrorLab(signal, __LINE__); return; }//Ndbcntr::execTCSEIZEREF() /*---------------------------------------------------------------------------*/ /*INITIALIZE VARIABLES AND RECORDS */ /*---------------------------------------------------------------------------*/ void Ndbcntr::initData(Signal* signal) { c_start.reset(); cmasterNodeId = 0; cnoStartNodes = 0; cnoWaitrep = 0; }//Ndbcntr::initData() /*---------------------------------------------------------------------------*/ /*RESET VARIABLES USED DURING THE START */ /*---------------------------------------------------------------------------*/ void Ndbcntr::resetStartVariables(Signal* signal) { cnoStartNodes = 0; cnoWaitrep6 = cnoWaitrep7 = 0; }//Ndbcntr::resetStartVariables() /*---------------------------------------------------------------------------*/ // SEND THE SIGNAL // INPUT CNDB_BLOCKS_COUNT /*---------------------------------------------------------------------------*/ void Ndbcntr::sendNdbSttor(Signal* signal) { NdbBlocksRecPtr ndbBlocksPtr; ndbBlocksPtr.i = cndbBlocksCount; ptrCheckGuard(ndbBlocksPtr, ZSIZE_NDB_BLOCKS_REC, ndbBlocksRec); NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend(); req->senderRef = reference(); req->nodeId = getOwnNodeId(); req->internalStartPhase = cinternalStartphase; req->typeOfStart = ctypeOfStart; req->masterNodeId = cmasterNodeId; for (int i = 0; i < 16; i++) { // Garbage req->config[i] = 0x88776655; //cfgBlockPtr.p->cfgData[i]; } //#define MAX_STARTPHASE 2 #ifdef TRACE_STTOR ndbout_c("sending NDB_STTOR(%d) to %s", cinternalStartphase, getBlockName( refToBlock(ndbBlocksPtr.p->blockref))); #endif if (refToBlock(ndbBlocksPtr.p->blockref) == DBDIH) req->typeOfStart = cdihStartType; sendSignal(ndbBlocksPtr.p->blockref, GSN_NDB_STTOR, signal, 22, JBB); cndbBlocksCount++; }//Ndbcntr::sendNdbSttor() /*---------------------------------------------------------------------------*/ // JUST SEND THE SIGNAL /*---------------------------------------------------------------------------*/ void Ndbcntr::sendSttorry(Signal* signal) { signal->theData[3] = ZSTART_PHASE_1; signal->theData[4] = ZSTART_PHASE_2; signal->theData[5] = ZSTART_PHASE_3; signal->theData[6] = ZSTART_PHASE_4; signal->theData[7] = ZSTART_PHASE_5; signal->theData[8] = ZSTART_PHASE_6; // skip simulated phase 7 signal->theData[9] = ZSTART_PHASE_8; signal->theData[10] = ZSTART_PHASE_9; signal->theData[11] = ZSTART_PHASE_END; sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 12, JBB); }//Ndbcntr::sendSttorry() void Ndbcntr::execDUMP_STATE_ORD(Signal* signal) { DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0]; Uint32 arg = dumpState->args[0]; if(arg == 13){ infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d", cstartPhase, cinternalStartphase, cndbBlocksCount); infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId); } if (arg == DumpStateOrd::NdbcntrTestStopOnError){ if (m_ctx.m_config.stopOnError() == true) ((Configuration&)m_ctx.m_config).stopOnError(false); const BlockReference tblockref = calcNdbCntrBlockRef(getOwnNodeId()); SystemError * const sysErr = (SystemError*)&signal->theData[0]; sysErr->errorCode = SystemError::TestStopOnError; sysErr->errorRef = reference(); sendSignal(tblockref, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA); } if (arg == DumpStateOrd::NdbcntrStopNodes) { NdbNodeBitmask mask; for(Uint32 i = 1; i<signal->getLength(); i++) mask.set(signal->theData[i]); StopReq* req = (StopReq*)signal->getDataPtrSend(); req->senderRef = RNIL; req->senderData = 123; req->requestInfo = 0; req->singleuser = 0; req->singleUserApi = 0; mask.copyto(NdbNodeBitmask::Size, req->nodes); StopReq::setPerformRestart(req->requestInfo, 1); StopReq::setNoStart(req->requestInfo, 1); StopReq::setStopNodes(req->requestInfo, 1); StopReq::setStopAbort(req->requestInfo, 1); sendSignal(reference(), GSN_STOP_REQ, signal, StopReq::SignalLength, JBB); return; } if (arg == 71) { #ifdef ERROR_INSERT if (signal->getLength() == 2) { c_error_insert_extra = signal->theData[1]; SET_ERROR_INSERT_VALUE(1002); } else if (ERROR_INSERTED(1002)) { CLEAR_ERROR_INSERT_VALUE; } #endif } }//Ndbcntr::execDUMP_STATE_ORD() void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{ NodeStateRep * const stateRep = (NodeStateRep *)&signal->theData[0]; if (newState.startLevel == NodeState::SL_STARTED) { CRASH_INSERTION(1000); } stateRep->nodeState = newState; stateRep->nodeState.masterNodeId = cmasterNodeId; stateRep->nodeState.setNodeGroup(c_nodeGroup); for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){ sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength, JBB); } } void Ndbcntr::execRESUME_REQ(Signal* signal){ //ResumeReq * const req = (ResumeReq *)&signal->theData[0]; //ResumeRef * const ref = (ResumeRef *)&signal->theData[0]; jamEntry(); signal->theData[0] = NDB_LE_SingleUser; signal->theData[1] = 2; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); //Uint32 senderData = req->senderData; //BlockReference senderRef = req->senderRef; NodeState newState(NodeState::SL_STARTED); updateNodeState(signal, newState); c_stopRec.stopReq.senderRef=0; } void Ndbcntr::execSTOP_REQ(Signal* signal){ StopReq * const req = (StopReq *)&signal->theData[0]; StopRef * const ref = (StopRef *)&signal->theData[0]; Uint32 singleuser = req->singleuser; jamEntry(); Uint32 senderData = req->senderData; BlockReference senderRef = req->senderRef; bool abort = StopReq::getStopAbort(req->requestInfo); bool stopnodes = StopReq::getStopNodes(req->requestInfo); if(!singleuser && (getNodeState().startLevel < NodeState::SL_STARTED || (abort && !stopnodes))) { /** * Node is not started yet * * So stop it quickly */ jam(); const Uint32 reqInfo = req->requestInfo; if(StopReq::getPerformRestart(reqInfo)){ jam(); StartOrd * startOrd = (StartOrd *)&signal->theData[0]; startOrd->restartInfo = reqInfo; sendSignal(CMVMI_REF, GSN_START_ORD, signal, 1, JBA); } else { jam(); sendSignal(CMVMI_REF, GSN_STOP_ORD, signal, 1, JBA); } return; } if(c_stopRec.stopReq.senderRef != 0 || (cmasterNodeId == getOwnNodeId() && !c_start.m_starting.isclear())) { /** * Requested a system shutdown */ if(!singleuser && StopReq::getSystemStop(req->requestInfo)){ jam(); sendSignalWithDelay(reference(), GSN_STOP_REQ, signal, 100, StopReq::SignalLength); return; } /** * Requested a node shutdown */ if(c_stopRec.stopReq.senderRef && StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)) ref->errorCode = StopRef::SystemShutdownInProgress; else ref->errorCode = StopRef::NodeShutdownInProgress; ref->senderData = senderData; ref->masterNodeId = cmasterNodeId; if (senderRef != RNIL) sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); return; } if (stopnodes && !abort) { jam(); ref->errorCode = StopRef::UnsupportedNodeShutdown; ref->senderData = senderData; ref->masterNodeId = cmasterNodeId; if (senderRef != RNIL) sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); return; } if (stopnodes && cmasterNodeId != getOwnNodeId()) { jam(); ref->errorCode = StopRef::MultiNodeShutdownNotMaster; ref->senderData = senderData; ref->masterNodeId = cmasterNodeId; if (senderRef != RNIL) sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); return; } c_stopRec.stopReq = * req; c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); if (stopnodes) { jam(); if(!c_stopRec.checkNodeFail(signal)) { jam(); return; } char buf[100]; NdbNodeBitmask mask; mask.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); infoEvent("Initiating shutdown abort of %s", mask.getText(buf)); ndbout_c("Initiating shutdown abort of %s", mask.getText(buf)); WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = StopRecord::SR_BLOCK_GCP_START_GCP; req->requestType = WaitGCPReq::BlockStartGcp; sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBB); return; } else if(!singleuser) { if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)) { jam(); if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)) { ((Configuration&)m_ctx.m_config).stopOnError(false); } } if(!c_stopRec.checkNodeFail(signal)) { jam(); return; } signal->theData[0] = NDB_LE_NDBStopStarted; signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); } else { signal->theData[0] = NDB_LE_SingleUser; signal->theData[1] = 0; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); } NodeState newState(NodeState::SL_STOPPING_1, StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); if(singleuser) { newState.setSingleUser(true); newState.setSingleUserApi(c_stopRec.stopReq.singleUserApi); } updateNodeState(signal, newState); signal->theData[0] = ZSHUTDOWN; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::StopRecord::checkTimeout(Signal* signal){ jamEntry(); if(!cntr.getNodeState().getSingleUserMode()) if(!checkNodeFail(signal)){ jam(); return; } switch(cntr.getNodeState().startLevel){ case NodeState::SL_STOPPING_1: checkApiTimeout(signal); break; case NodeState::SL_STOPPING_2: checkTcTimeout(signal); break; case NodeState::SL_STOPPING_3: checkLqhTimeout_1(signal); break; case NodeState::SL_STOPPING_4: checkLqhTimeout_2(signal); break; case NodeState::SL_SINGLEUSER: break; default: ndbrequire(false); } } bool Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ jam(); if(StopReq::getSystemStop(stopReq.requestInfo)){ jam(); return true; } /** * Check if I can survive me stopping */ NdbNodeBitmask ndbMask; ndbMask.assign(cntr.c_startedNodes); if (StopReq::getStopNodes(stopReq.requestInfo)) { NdbNodeBitmask tmp; tmp.assign(NdbNodeBitmask::Size, stopReq.nodes); NdbNodeBitmask ndbStopNodes; ndbStopNodes.assign(NdbNodeBitmask::Size, stopReq.nodes); ndbStopNodes.bitAND(ndbMask); ndbStopNodes.copyto(NdbNodeBitmask::Size, stopReq.nodes); ndbMask.bitANDC(tmp); bool allNodesStopped = true; int i ; for( i = 0; i < (int) NdbNodeBitmask::Size; i++ ){ if ( stopReq.nodes[i] != 0 ){ allNodesStopped = false; break; } } if ( allNodesStopped ) { StopConf * const stopConf = (StopConf *)&signal->theData[0]; stopConf->senderData = stopReq.senderData; stopConf->nodeState = (Uint32) NodeState::SL_NOTHING; cntr.sendSignal(stopReq.senderRef, GSN_STOP_CONF, signal, StopConf::SignalLength, JBB); stopReq.senderRef = 0; return false; } } else { ndbMask.clear(cntr.getOwnNodeId()); } CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0]; sd->blockRef = cntr.reference(); sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck; sd->mask = ndbMask; cntr.EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal, CheckNodeGroups::SignalLength); jamEntry(); switch (sd->output) { case CheckNodeGroups::Win: case CheckNodeGroups::Partitioning: return true; break; } StopRef * const ref = (StopRef *)&signal->theData[0]; ref->senderData = stopReq.senderData; ref->errorCode = StopRef::NodeShutdownWouldCauseSystemCrash; ref->masterNodeId = cntr.cmasterNodeId; const BlockReference bref = stopReq.senderRef; if (bref != RNIL) cntr.sendSignal(bref, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); stopReq.senderRef = 0; if (cntr.getNodeState().startLevel != NodeState::SL_SINGLEUSER) { NodeState newState(NodeState::SL_STARTED); cntr.updateNodeState(signal, newState); } signal->theData[0] = NDB_LE_NDBStopAborted; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB); return false; } void Ndbcntr::StopRecord::checkApiTimeout(Signal* signal){ const Int32 timeout = stopReq.apiTimeout; const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout; const NDB_TICKS now = NdbTick_CurrentMillisecond(); if((timeout >= 0 && now >= alarm)){ // || checkWithApiInSomeMagicWay) jam(); NodeState newState(NodeState::SL_STOPPING_2, StopReq::getSystemStop(stopReq.requestInfo)); if(stopReq.singleuser) { newState.setSingleUser(true); newState.setSingleUserApi(stopReq.singleUserApi); } cntr.updateNodeState(signal, newState); stopInitiatedTime = now; } signal->theData[0] = ZSHUTDOWN; cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::StopRecord::checkTcTimeout(Signal* signal){ const Int32 timeout = stopReq.transactionTimeout; const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout; const NDB_TICKS now = NdbTick_CurrentMillisecond(); if((timeout >= 0 && now >= alarm)){ // || checkWithTcInSomeMagicWay) jam(); if(stopReq.getSystemStop(stopReq.requestInfo) || stopReq.singleuser){ jam(); if(stopReq.singleuser) { jam(); AbortAllReq * req = (AbortAllReq*)&signal->theData[0]; req->senderRef = cntr.reference(); req->senderData = 12; cntr.sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal, AbortAllReq::SignalLength, JBB); } else { WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = cntr.reference(); req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN; req->requestType = WaitGCPReq::CompleteForceStart; cntr.sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBB); } } else { jam(); StopPermReq * req = (StopPermReq*)&signal->theData[0]; req->senderRef = cntr.reference(); req->senderData = 12; cntr.sendSignal(DBDIH_REF, GSN_STOP_PERM_REQ, signal, StopPermReq::SignalLength, JBB); } return; } signal->theData[0] = ZSHUTDOWN; cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::execSTOP_PERM_REF(Signal* signal){ //StopPermRef* const ref = (StopPermRef*)&signal->theData[0]; jamEntry(); signal->theData[0] = ZSHUTDOWN; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::execSTOP_PERM_CONF(Signal* signal){ jamEntry(); AbortAllReq * req = (AbortAllReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = 12; sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal, AbortAllReq::SignalLength, JBB); } void Ndbcntr::execABORT_ALL_CONF(Signal* signal){ jamEntry(); if(c_stopRec.stopReq.singleuser) { jam(); NodeState newState(NodeState::SL_SINGLEUSER); newState.setSingleUser(true); newState.setSingleUserApi(c_stopRec.stopReq.singleUserApi); updateNodeState(signal, newState); c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); StopConf * const stopConf = (StopConf *)&signal->theData[0]; stopConf->senderData = c_stopRec.stopReq.senderData; stopConf->nodeState = (Uint32) NodeState::SL_SINGLEUSER; sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_CONF, signal, StopConf::SignalLength, JBB); c_stopRec.stopReq.senderRef = 0; // the command is done signal->theData[0] = NDB_LE_SingleUser; signal->theData[1] = 1; signal->theData[2] = c_stopRec.stopReq.singleUserApi; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); } else { jam(); NodeState newState(NodeState::SL_STOPPING_3, StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); updateNodeState(signal, newState); c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); signal->theData[0] = ZSHUTDOWN; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } } void Ndbcntr::execABORT_ALL_REF(Signal* signal){ jamEntry(); StopRef * const stopRef = (StopRef *)&signal->theData[0]; stopRef->senderData = c_stopRec.stopReq.senderData; stopRef->errorCode = StopRef::TransactionAbortFailed; stopRef->masterNodeId = cmasterNodeId; sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); } void Ndbcntr::StopRecord::checkLqhTimeout_1(Signal* signal){ const Int32 timeout = stopReq.readOperationTimeout; const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout; const NDB_TICKS now = NdbTick_CurrentMillisecond(); if((timeout >= 0 && now >= alarm)){ // || checkWithLqhInSomeMagicWay) jam(); ChangeNodeStateReq * req = (ChangeNodeStateReq*)&signal->theData[0]; NodeState newState(NodeState::SL_STOPPING_4, StopReq::getSystemStop(stopReq.requestInfo)); req->nodeState = newState; req->senderRef = cntr.reference(); req->senderData = 12; cntr.sendSignal(DBLQH_REF, GSN_CHANGE_NODE_STATE_REQ, signal, ChangeNodeStateReq::SignalLength, JBB); return; } signal->theData[0] = ZSHUTDOWN; cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::execCHANGE_NODE_STATE_CONF(Signal* signal) { jamEntry(); /** * stop replication stream */ signal->theData[0] = reference(); signal->theData[1] = 12; sendSignal(SUMA_REF, GSN_STOP_ME_REQ, signal, 2, JBB); } void Ndbcntr::execSTOP_ME_REF(Signal* signal){ jamEntry(); ndbrequire(false); } void Ndbcntr::execSTOP_ME_CONF(Signal* signal){ jamEntry(); const StopMeConf * conf = CAST_CONSTPTR(StopMeConf, signal->getDataPtr()); if (conf->senderData == 12) { /** * Remove node from transactions */ signal->theData[0] = reference(); signal->theData[1] = 13; sendSignal(DBDIH_REF, GSN_STOP_ME_REQ, signal, 2, JBB); return; } NodeState newState(NodeState::SL_STOPPING_4, StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); updateNodeState(signal, newState); c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); signal->theData[0] = ZSHUTDOWN; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::StopRecord::checkLqhTimeout_2(Signal* signal){ const Int32 timeout = stopReq.operationTimeout; const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout; const NDB_TICKS now = NdbTick_CurrentMillisecond(); if((timeout >= 0 && now >= alarm)){ // || checkWithLqhInSomeMagicWay) jam(); if(StopReq::getPerformRestart(stopReq.requestInfo)){ jam(); StartOrd * startOrd = (StartOrd *)&signal->theData[0]; startOrd->restartInfo = stopReq.requestInfo; cntr.sendSignal(CMVMI_REF, GSN_START_ORD, signal, 2, JBA); } else { jam(); cntr.sendSignal(CMVMI_REF, GSN_STOP_ORD, signal, 1, JBA); } return; } signal->theData[0] = ZSHUTDOWN; cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1); } void Ndbcntr::execWAIT_GCP_REF(Signal* signal){ jamEntry(); //WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0]; WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN; req->requestType = WaitGCPReq::CompleteForceStart; sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBB); } void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){ jamEntry(); WaitGCPConf* conf = (WaitGCPConf*)signal->getDataPtr(); switch(conf->senderData){ case StopRecord::SR_BLOCK_GCP_START_GCP: { jam(); /** * */ if(!c_stopRec.checkNodeFail(signal)) { jam(); goto unblock; } WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = StopRecord::SR_WAIT_COMPLETE_GCP; req->requestType = WaitGCPReq::CompleteIfRunning; sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBB); return; } case StopRecord::SR_UNBLOCK_GCP_START_GCP: { jam(); return; } case StopRecord::SR_WAIT_COMPLETE_GCP: { jam(); if(!c_stopRec.checkNodeFail(signal)) { jam(); goto unblock; } NdbNodeBitmask tmp; tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); c_stopRec.m_stop_req_counter = tmp; NodeReceiverGroup rg(QMGR, tmp); StopReq * stopReq = (StopReq *)&signal->theData[0]; * stopReq = c_stopRec.stopReq; stopReq->senderRef = reference(); sendSignal(rg, GSN_STOP_REQ, signal, StopReq::SignalLength, JBA); c_stopRec.m_state = StopRecord::SR_QMGR_STOP_REQ; return; } case StopRecord::SR_CLUSTER_SHUTDOWN: { jam(); break; } } { ndbrequire(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); NodeState newState(NodeState::SL_STOPPING_3, true); /** * Inform QMGR so that arbitrator won't kill us */ NodeStateRep * rep = (NodeStateRep *)&signal->theData[0]; rep->nodeState = newState; rep->nodeState.masterNodeId = cmasterNodeId; rep->nodeState.setNodeGroup(c_nodeGroup); EXECUTE_DIRECT(QMGR, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength); if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ jam(); StartOrd * startOrd = (StartOrd *)&signal->theData[0]; startOrd->restartInfo = c_stopRec.stopReq.requestInfo; sendSignalWithDelay(CMVMI_REF, GSN_START_ORD, signal, 500, StartOrd::SignalLength); } else { jam(); sendSignalWithDelay(CMVMI_REF, GSN_STOP_ORD, signal, 500, 1); } return; } unblock: WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; req->senderRef = reference(); req->senderData = StopRecord::SR_UNBLOCK_GCP_START_GCP; req->requestType = WaitGCPReq::UnblockStartGcp; sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, WaitGCPReq::SignalLength, JBB); } void Ndbcntr::execSTOP_CONF(Signal* signal) { jamEntry(); StopConf *conf = (StopConf*)signal->getDataPtr(); ndbrequire(c_stopRec.m_state == StopRecord::SR_QMGR_STOP_REQ); c_stopRec.m_stop_req_counter.clearWaitingFor(conf->nodeId); if (c_stopRec.m_stop_req_counter.done()) { char buf[100]; NdbNodeBitmask mask; mask.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes); infoEvent("Stopping of %s", mask.getText(buf)); ndbout_c("Stopping of %s", mask.getText(buf)); /** * Kill any node... */ FailRep * const failRep = (FailRep *)&signal->theData[0]; failRep->failCause = FailRep::ZMULTI_NODE_SHUTDOWN; failRep->failSourceNodeId = getOwnNodeId(); NodeReceiverGroup rg(QMGR, c_clusterNodes); Uint32 nodeId = 0; while ((nodeId = NdbNodeBitmask::find(c_stopRec.stopReq.nodes, nodeId+1)) != NdbNodeBitmask::NotFound) { failRep->failNodeId = nodeId; sendSignal(rg, GSN_FAIL_REP, signal, FailRep::SignalLength, JBA); } c_stopRec.m_state = StopRecord::SR_WAIT_NODE_FAILURES; return; } } void Ndbcntr::execSTTORRY(Signal* signal){ jamEntry(); 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(); c_missra.execSTART_ORD(signal); } #define CLEAR_DX 13 #define CLEAR_LCP 3 #define CLEAR_DD 2 // FileSystemPathDataFiles FileSystemPathUndoFiles void Ndbcntr::clearFilesystem(Signal* signal) { jam(); FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend(); req->userReference = reference(); req->userPointer = 0; req->directory = 1; req->ownDirectory = 1; const Uint32 DX = CLEAR_DX; const Uint32 LCP = CLEAR_DX + CLEAR_LCP; const Uint32 DD = CLEAR_DX + CLEAR_LCP + CLEAR_DD; if (c_fsRemoveCount < DX) { FsOpenReq::setVersion(req->fileNumber, 3); FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL); // Can by any... FsOpenReq::v1_setDisk(req->fileNumber, c_fsRemoveCount); } else if (c_fsRemoveCount < LCP) { FsOpenReq::setVersion(req->fileNumber, 5); FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA); FsOpenReq::v5_setLcpNo(req->fileNumber, c_fsRemoveCount - CLEAR_DX); FsOpenReq::v5_setTableId(req->fileNumber, 0); FsOpenReq::v5_setFragmentId(req->fileNumber, 0); } else if (c_fsRemoveCount < DD) { req->ownDirectory = 0; FsOpenReq::setVersion(req->fileNumber, 6); FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA); FsOpenReq::v5_setLcpNo(req->fileNumber, FsOpenReq::BP_DD_DF + c_fsRemoveCount - LCP); } else { ndbrequire(false); } sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, FsRemoveReq::SignalLength, JBA); c_fsRemoveCount++; } void Ndbcntr::execFSREMOVECONF(Signal* signal){ jamEntry(); if(c_fsRemoveCount == CLEAR_DX + CLEAR_LCP + CLEAR_DD){ jam(); sendSttorry(signal); } else { jam(); ndbrequire(c_fsRemoveCount < CLEAR_DX + CLEAR_LCP + CLEAR_DD); clearFilesystem(signal); }//if } void Ndbcntr::Missra::execSTART_ORD(Signal* signal){ signal->theData[0] = NDB_LE_NDBStartStarted; signal->theData[1] = NDB_VERSION; signal->theData[2] = NDB_MYSQL_VERSION_D; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, 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 = readConfigOrder[currentBlockIndex]; #if 0 ndbout_c("sending READ_CONFIG_REQ to %s(ref=%x index=%d)", getBlockName( refToBlock(ref)), ref, currentBlockIndex); #endif /** * send delayed so that alloc gets "time-sliced" */ cntr.sendSignalWithDelay(ref, GSN_READ_CONFIG_REQ, signal, 1, ReadConfigReq::SignalLength); return; } /** * Finished... */ currentStartPhase = 0; for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){ if(ALL_BLOCKS[i].NextSP < currentStartPhase) currentStartPhase = ALL_BLOCKS[i].NextSP; } 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(readConfigOrder[currentBlockIndex]) == 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)); /** * Update next start phase */ for (Uint32 i = 3; i < 25; i++){ jam(); if (signal->theData[i] > currentStartPhase){ jam(); ALL_BLOCKS[currentBlockIndex].NextSP = signal->theData[i]; break; } } currentBlockIndex++; sendNextSTTOR(signal); } void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){ for(; currentStartPhase < 255 ; currentStartPhase++, g_currentStartPhase = currentStartPhase){ jam(); #ifdef ERROR_INSERT if (cntr.cerrorInsert == 1002 && cntr.c_error_insert_extra == currentStartPhase) { signal->theData[0] = ZBLOCK_STTOR; cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1); return; } #endif const Uint32 start = currentBlockIndex; for(; currentBlockIndex < ALL_BLOCKS_SZ; currentBlockIndex++){ jam(); if(ALL_BLOCKS[currentBlockIndex].NextSP == currentStartPhase){ jam(); signal->theData[0] = 0; signal->theData[1] = currentStartPhase; signal->theData[2] = 0; signal->theData[3] = 0; signal->theData[4] = 0; signal->theData[5] = 0; signal->theData[6] = 0; signal->theData[7] = cntr.ctypeOfStart; const BlockReference ref = ALL_BLOCKS[currentBlockIndex].Ref; #ifdef MAX_STARTPHASE ndbrequire(currentStartPhase <= MAX_STARTPHASE); #endif #ifdef TRACE_STTOR ndbout_c("sending STTOR(%d) to %s(ref=%x index=%d)", currentStartPhase, getBlockName( refToBlock(ref)), ref, currentBlockIndex); #endif if (refToBlock(ref) == DBDIH) signal->theData[7] = cntr.cdihStartType; cntr.sendSignal(ref, GSN_STTOR, signal, 8, JBB); return; } } currentBlockIndex = 0; NodeState newState(NodeState::SL_STARTING, currentStartPhase, (NodeState::StartType)cntr.ctypeOfStart); cntr.updateNodeState(signal, newState); if(start != 0) { /** * At least one wanted this start phase, record & report it */ jam(); g_eventLogger->info("Start phase %u completed", currentStartPhase); signal->theData[0] = NDB_LE_StartPhaseCompleted; signal->theData[1] = currentStartPhase; signal->theData[2] = cntr.ctypeOfStart; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); /** * Check if we should wait before proceeding with * next startphase * * New code guarantees that before starting X * that all other nodes (in system restart/initial start) * want to start a startphase >= X */ if (cntr.wait_sp(signal, currentStartPhase + 1)) { jam(); currentStartPhase++; g_currentStartPhase = currentStartPhase; return; } } } g_eventLogger->info("Node started"); signal->theData[0] = NDB_LE_NDBStartCompleted; signal->theData[1] = NDB_VERSION; signal->theData[2] = NDB_MYSQL_VERSION_D; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); NodeState newState(NodeState::SL_STARTED); cntr.updateNodeState(signal, newState); NodeReceiverGroup rg(NDBCNTR, cntr.c_clusterNodes); signal->theData[0] = cntr.getOwnNodeId(); cntr.sendSignal(rg, GSN_CNTR_START_REP, signal, 1, JBB); } void Ndbcntr::execCREATE_NODEGROUP_IMPL_REQ(Signal* signal) { jamEntry(); CreateNodegroupImplReq reqCopy = *(CreateNodegroupImplReq*)signal->getDataPtr(); CreateNodegroupImplReq *req = &reqCopy; if (req->requestType == CreateNodegroupImplReq::RT_COMMIT) { jam(); Uint32 save = c_nodeGroup; getNodeGroup(signal); if (save != c_nodeGroup) { jam(); updateNodeState(signal, getNodeState()); } } { CreateNodegroupImplConf* conf = (CreateNodegroupImplConf*)signal->getDataPtrSend(); conf->senderRef = reference(); conf->senderData = req->senderData; sendSignal(req->senderRef, GSN_CREATE_NODEGROUP_IMPL_CONF, signal, CreateNodegroupImplConf::SignalLength, JBB); } } void Ndbcntr::execDROP_NODEGROUP_IMPL_REQ(Signal* signal) { jamEntry(); DropNodegroupImplReq reqCopy = *(DropNodegroupImplReq*)signal->getDataPtr(); DropNodegroupImplReq *req = &reqCopy; if (req->requestType == DropNodegroupImplReq::RT_COMPLETE) { jam(); Uint32 save = c_nodeGroup; getNodeGroup(signal); if (save != c_nodeGroup) { jam(); updateNodeState(signal, getNodeState()); } } { DropNodegroupImplConf* conf = (DropNodegroupImplConf*)signal->getDataPtrSend(); conf->senderRef = reference(); conf->senderData = req->senderData; sendSignal(req->senderRef, GSN_DROP_NODEGROUP_IMPL_CONF, signal, DropNodegroupImplConf::SignalLength, JBB); } } template class Vector<ddentry>;