ndb - bug#18612

  post weeked fixes :-)
  change impl. to use READ_NODESREQ to query state of other qmgr(partition)
    this as it has no (current) side effects, so that it's possible only to kill
    starting cluster (if one started and one starting)
parent d367f635
...@@ -36,7 +36,8 @@ class FailRep { ...@@ -36,7 +36,8 @@ class FailRep {
public: public:
STATIC_CONST( SignalLength = 2 ); STATIC_CONST( SignalLength = 2 );
STATIC_CONST( ExtraLength = 1 + NdbNodeBitmask::Size );
enum FailCause { enum FailCause {
ZOWN_FAILURE=0, ZOWN_FAILURE=0,
ZOTHER_NODE_WHEN_WE_START=1, ZOTHER_NODE_WHEN_WE_START=1,
...@@ -45,13 +46,19 @@ public: ...@@ -45,13 +46,19 @@ public:
ZHEARTBEAT_FAILURE=4, ZHEARTBEAT_FAILURE=4,
ZLINK_FAILURE=5, ZLINK_FAILURE=5,
ZOTHERNODE_FAILED_DURING_START=6, ZOTHERNODE_FAILED_DURING_START=6,
ZMULTI_NODE_SHUTDOWN = 7 ZMULTI_NODE_SHUTDOWN = 7,
ZPARTITIONED_CLUSTER = 8
}; };
private: private:
Uint32 failNodeId; Uint32 failNodeId;
Uint32 failCause; Uint32 failCause;
/**
* Used when failCause == ZPARTITIONED_CLUSTER
*/
Uint32 president;
Uint32 partition[NdbNodeBitmask::Size];
}; };
......
...@@ -124,7 +124,7 @@ public: ...@@ -124,7 +124,7 @@ public:
* *
* i.e. nodes that connect to use, when we already have elected president * i.e. nodes that connect to use, when we already have elected president
*/ */
NdbNodeBitmask c_cmregreq_nodes; NdbNodeBitmask c_readnodes_nodes;
Uint32 c_maxDynamicId; Uint32 c_maxDynamicId;
...@@ -233,6 +233,8 @@ private: ...@@ -233,6 +233,8 @@ private:
void execREAD_NODESREQ(Signal* signal); void execREAD_NODESREQ(Signal* signal);
void execSET_VAR_REQ(Signal* signal); void execSET_VAR_REQ(Signal* signal);
void execREAD_NODESREF(Signal* signal);
void execREAD_NODESCONF(Signal* signal);
void execAPI_VERSION_REQ(Signal* signal); void execAPI_VERSION_REQ(Signal* signal);
void execAPI_BROADCAST_REP(Signal* signal); void execAPI_BROADCAST_REP(Signal* signal);
...@@ -249,6 +251,8 @@ private: ...@@ -249,6 +251,8 @@ private:
void execARBIT_STOPREP(Signal* signal); void execARBIT_STOPREP(Signal* signal);
// Statement blocks // Statement blocks
void check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn);
void node_failed(Signal* signal, Uint16 aFailedNode); void node_failed(Signal* signal, Uint16 aFailedNode);
void checkStartInterface(Signal* signal); void checkStartInterface(Signal* signal);
void failReport(Signal* signal, void failReport(Signal* signal,
...@@ -268,7 +272,6 @@ private: ...@@ -268,7 +272,6 @@ private:
void startphase1(Signal* signal); void startphase1(Signal* signal);
void electionWon(Signal* signal); void electionWon(Signal* signal);
void cmInfoconf010Lab(Signal* signal); void cmInfoconf010Lab(Signal* signal);
bool check_cmregreq_reply(Signal* signal, Uint32 nodeId, Uint32 gsn);
void apiHbHandlingLab(Signal* signal); void apiHbHandlingLab(Signal* signal);
void timerHandlingLab(Signal* signal); void timerHandlingLab(Signal* signal);
......
...@@ -94,6 +94,9 @@ Qmgr::Qmgr(const class Configuration & conf) ...@@ -94,6 +94,9 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_ARBIT_CHOOSEREF, &Qmgr::execARBIT_CHOOSEREF); addRecSignal(GSN_ARBIT_CHOOSEREF, &Qmgr::execARBIT_CHOOSEREF);
addRecSignal(GSN_ARBIT_STOPREP, &Qmgr::execARBIT_STOPREP); addRecSignal(GSN_ARBIT_STOPREP, &Qmgr::execARBIT_STOPREP);
addRecSignal(GSN_READ_NODESREF, &Qmgr::execREAD_NODESREF);
addRecSignal(GSN_READ_NODESCONF, &Qmgr::execREAD_NODESCONF);
initData(); initData();
}//Qmgr::Qmgr() }//Qmgr::Qmgr()
......
...@@ -369,13 +369,29 @@ void Qmgr::execCONNECT_REP(Signal* signal) ...@@ -369,13 +369,29 @@ void Qmgr::execCONNECT_REP(Signal* signal)
} }
ndbrequire(!c_start.m_nodes.isWaitingFor(nodeId)); ndbrequire(!c_start.m_nodes.isWaitingFor(nodeId));
ndbrequire(!c_cmregreq_nodes.get(nodeId)); ndbrequire(!c_readnodes_nodes.get(nodeId));
c_cmregreq_nodes.set(nodeId); c_readnodes_nodes.set(nodeId);
sendCmRegReq(signal, nodeId); signal->theData[0] = reference();
c_regReqReqSent--; sendSignal(calcQmgrBlockRef(nodeId), GSN_READ_NODESREQ, signal, 1, JBA);
return; return;
}//Qmgr::execCONNECT_REP() }//Qmgr::execCONNECT_REP()
void
Qmgr::execREAD_NODESCONF(Signal* signal)
{
check_readnodes_reply(signal,
refToNode(signal->getSendersBlockRef()),
GSN_READ_NODESCONF);
}
void
Qmgr::execREAD_NODESREF(Signal* signal)
{
check_readnodes_reply(signal,
refToNode(signal->getSendersBlockRef()),
GSN_READ_NODESREF);
}
/*******************************/ /*******************************/
/* CM_INFOCONF */ /* CM_INFOCONF */
/*******************************/ /*******************************/
...@@ -668,12 +684,6 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -668,12 +684,6 @@ void Qmgr::execCM_REGCONF(Signal* signal)
const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0]; const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
Uint32 presidentNodeId = cmRegConf->presidentNodeId; Uint32 presidentNodeId = cmRegConf->presidentNodeId;
if (check_cmregreq_reply(signal, presidentNodeId, GSN_CM_REGCONF))
{
jam();
return;
}
if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) { if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) {
jam(); jam();
char buf[128]; char buf[128];
...@@ -731,8 +741,8 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -731,8 +741,8 @@ void Qmgr::execCM_REGCONF(Signal* signal)
return; return;
}//Qmgr::execCM_REGCONF() }//Qmgr::execCM_REGCONF()
bool void
Qmgr::check_cmregreq_reply(Signal* signal, Uint32 nodeId, Uint32 gsn) Qmgr::check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn)
{ {
NodeRecPtr myNodePtr; NodeRecPtr myNodePtr;
myNodePtr.i = getOwnNodeId(); myNodePtr.i = getOwnNodeId();
...@@ -741,117 +751,65 @@ Qmgr::check_cmregreq_reply(Signal* signal, Uint32 nodeId, Uint32 gsn) ...@@ -741,117 +751,65 @@ Qmgr::check_cmregreq_reply(Signal* signal, Uint32 nodeId, Uint32 gsn)
NodeRecPtr nodePtr; NodeRecPtr nodePtr;
nodePtr.i = nodeId; nodePtr.i = nodeId;
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec); ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
/**
* Try to decide if replying node
* knows who is president
*/
Uint32 president_reply = RNIL;
switch(gsn){
case GSN_CM_REGREF:{
jam();
CmRegRef* ref = (CmRegRef*)signal->getDataPtr();
switch(ref->errorCode){
case CmRegRef::ZBUSY:
case CmRegRef::ZBUSY_PRESIDENT:
case CmRegRef::ZBUSY_TO_PRES:
jam();
/**
* Only president replies this
*/
ndbrequire(nodeId == ref->presidentCandidate);
president_reply = nodeId;
break;
case CmRegRef::ZNOT_PRESIDENT:
jam();
president_reply = ref->presidentCandidate;
break;
case CmRegRef::ZNOT_IN_CFG:
case CmRegRef::ZNOT_DEAD:
case CmRegRef::ZELECTION:
// Neither of these replies give certain president knowledge
jam();
}
break;
}
case GSN_CM_REGCONF:
jam();
president_reply = nodeId;
break;
}
char buf[256];
switch(c_start.m_gsn){
case GSN_CM_REGREQ:
jam();
ndbrequire(c_start.m_nodes.isWaitingFor(nodeId));
ndbrequire(c_cmregreq_nodes.isclear());
ndbrequire(myNodePtr.p->phase == ZSTARTING);
return false;
case GSN_CM_NODEINFOREQ:
jam();
ndbrequire(myNodePtr.p->phase == ZSTARTING); ndbrequire(c_readnodes_nodes.get(nodeId));
if (c_start.m_nodes.isWaitingFor(nodeId)) ReadNodesConf* conf = (ReadNodesConf*)signal->getDataPtr();
{ if (gsn == GSN_READ_NODESREF)
jam(); {
/**
* We're waiting for CM_NODEINFO
*/
if (gsn == GSN_CM_REGREF)
{
jam();
return false;
}
jam();
BaseString::snprintf(buf, sizeof(buf),
"Partitioned cluster! check StartPartialTimeout, "
" received CM_REGCONF from %d"
" while waiting for GSN_CM_NODEINFOCONF."
" president=%d",
nodeId, cpresident);
goto die_direct;
}
goto check_reply;
default:
case GSN_CM_NODEINFOCONF:
jam(); jam();
ndbrequire(myNodePtr.p->phase == ZRUNNING); retry:
goto check_reply; signal->theData[0] = reference();
sendSignal(calcQmgrBlockRef(nodeId), GSN_READ_NODESREQ, signal, 1, JBA);
return;
} }
check_reply: if (conf->masterNodeId == ZNIL)
jam();
c_cmregreq_nodes.clear(nodeId);
if (gsn == GSN_CM_REGCONF)
{ {
jam(); jam();
BaseString::snprintf(buf, sizeof(buf), goto retry;
"Partitioned cluster! check StartPartialTimeout, "
" received CM_REGCONF"
" from %d I think president: %d",
nodeId, cpresident);
goto die_direct;
} }
if (president_reply != RNIL && president_reply != cpresident) Uint32 president = conf->masterNodeId;
if (president == cpresident)
{ {
jam(); jam();
BaseString::snprintf(buf, sizeof(buf), c_readnodes_nodes.clear(nodeId);
"Partitioned cluster! check StartPartialTimeout, " return;
" received CM_REGREF from %d specifying president as"
" %d, president: %d",
nodeId, president_reply, cpresident);
goto die_direct;
} }
return true;
die_direct: char buf[255];
BaseString::snprintf(buf, sizeof(buf),
"Partitioned cluster! check StartPartialTimeout, "
" node %d thinks %d is president, "
" I think president is: %d",
nodeId, president, cpresident);
ndbout_c(buf); ndbout_c(buf);
CRASH_INSERTION(933);
if (getNodeState().startLevel == NodeState::SL_STARTED)
{
jam();
NdbNodeBitmask part;
part.assign(NdbNodeBitmask::Size, conf->clusterNodes);
FailRep* rep = (FailRep*)signal->getDataPtrSend();
rep->failCause = FailRep::ZPARTITIONED_CLUSTER;
rep->president = cpresident;
c_clusterNodes.copyto(NdbNodeBitmask::Size, rep->partition);
Uint32 ref = calcQmgrBlockRef(nodeId);
Uint32 i = 0;
while((i = part.find(i + 1)) != NdbNodeBitmask::NotFound)
{
if (i == nodeId)
continue;
rep->failNodeId = i;
sendSignal(ref, GSN_FAIL_REP, signal, FailRep::SignalLength, JBA);
}
rep->failNodeId = nodeId;
sendSignal(ref, GSN_FAIL_REP, signal, FailRep::SignalLength, JBB);
return;
}
CRASH_INSERTION(932); CRASH_INSERTION(932);
progError(__LINE__, progError(__LINE__,
...@@ -899,12 +857,6 @@ void Qmgr::execCM_REGREF(Signal* signal) ...@@ -899,12 +857,6 @@ void Qmgr::execCM_REGREF(Signal* signal)
Uint32 candidate = signal->theData[3]; Uint32 candidate = signal->theData[3];
DEBUG_START3(signal, TrefuseReason); DEBUG_START3(signal, TrefuseReason);
if (check_cmregreq_reply(signal, TaddNodeno, GSN_CM_REGREF))
{
jam();
return;
}
c_regReqReqRecv++; c_regReqReqRecv++;
// Ignore block reference in data[0] // Ignore block reference in data[0]
...@@ -2069,7 +2021,7 @@ void Qmgr::execDISCONNECT_REP(Signal* signal) ...@@ -2069,7 +2021,7 @@ void Qmgr::execDISCONNECT_REP(Signal* signal)
const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0]; const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
const Uint32 nodeId = rep->nodeId; const Uint32 nodeId = rep->nodeId;
c_connectedNodes.clear(nodeId); c_connectedNodes.clear(nodeId);
c_cmregreq_nodes.clear(nodeId); c_readnodes_nodes.clear(nodeId);
NodeRecPtr nodePtr; NodeRecPtr nodePtr;
nodePtr.i = getOwnNodeId(); nodePtr.i = getOwnNodeId();
...@@ -2342,13 +2294,16 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2342,13 +2294,16 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
failedNodePtr.i = aFailedNode; failedNodePtr.i = aFailedNode;
ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
FailRep* rep = (FailRep*)signal->getDataPtr();
check_multi_node_shutdown(signal); check_multi_node_shutdown(signal);
if (failedNodePtr.i == getOwnNodeId()) { if (failedNodePtr.i == getOwnNodeId()) {
jam(); jam();
Uint32 code = 0;
const char * msg = 0; const char * msg = 0;
char extra[100];
switch(aFailCause){ switch(aFailCause){
case FailRep::ZOWN_FAILURE: case FailRep::ZOWN_FAILURE:
msg = "Own failure"; msg = "Own failure";
...@@ -2369,17 +2324,46 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2369,17 +2324,46 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
case FailRep::ZLINK_FAILURE: case FailRep::ZLINK_FAILURE:
msg = "Connection failure"; msg = "Connection failure";
break; break;
case FailRep::ZPARTITIONED_CLUSTER:
{
code = ERR_ARBIT_SHUTDOWN;
char buf1[100], buf2[100];
c_clusterNodes.getText(buf1);
if (signal->getLength()== FailRep::SignalLength + FailRep::ExtraLength &&
signal->header.theVerId_signalNumber == GSN_FAIL_REP)
{
jam();
NdbNodeBitmask part;
part.assign(NdbNodeBitmask::Size, rep->partition);
part.getText(buf2);
BaseString::snprintf(extra, sizeof(extra),
"Partitioned cluster!"
" Our cluster: %s other cluster: %s",
buf1, buf2);
}
else
{
jam();
BaseString::snprintf(extra, sizeof(extra),
"Partitioned cluster!"
" Our cluster: %s ", buf1);
}
msg = extra;
break;
}
} }
char buf[100]; CRASH_INSERTION(932);
BaseString::snprintf(buf, 100,
char buf[255];
BaseString::snprintf(buf, sizeof(buf),
"We(%u) have been declared dead by %u reason: %s(%u)", "We(%u) have been declared dead by %u reason: %s(%u)",
getOwnNodeId(), getOwnNodeId(),
refToNode(signal->getSendersBlockRef()), refToNode(signal->getSendersBlockRef()),
aFailCause, aFailCause,
msg ? msg : "<Unknown>"); msg ? msg : "<Unknown>");
progError(__LINE__, 0, buf); progError(__LINE__, code, buf);
return; return;
}//if }//if
......
...@@ -753,13 +753,13 @@ runBug18612(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -753,13 +753,13 @@ runBug18612(NDBT_Context* ctx, NDBT_Step* step){
if (restarter.dumpStateAllNodes(dump, 2)) if (restarter.dumpStateAllNodes(dump, 2))
return NDBT_FAILED; return NDBT_FAILED;
if (restarter.waitClusterNoStart()) if (restarter.waitNodesNoStart(partition0, cnt/2))
return NDBT_FAILED; return NDBT_FAILED;
for (Uint32 i = 0; i<cnt/2; i++) for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.restartOneDbNode(partition0[i], true, true, true)) if (restarter.restartOneDbNode(partition0[i], true, true, true))
return NDBT_FAILED; return NDBT_FAILED;
if (restarter.waitNodesNoStart(partition0, cnt/2)) if (restarter.waitNodesNoStart(partition0, cnt/2))
return NDBT_FAILED; return NDBT_FAILED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment