Commit 7363712b authored by unknown's avatar unknown

Merge perch.ndb.mysql.com:/home/jonas/src/50-work

into  perch.ndb.mysql.com:/home/jonas/src/mysql-5.0

parents f7b039cc ec9b46a9
...@@ -30,12 +30,17 @@ class CmRegReq { ...@@ -30,12 +30,17 @@ class CmRegReq {
friend class Qmgr; friend class Qmgr;
public: public:
STATIC_CONST( SignalLength = 3 ); STATIC_CONST( SignalLength = 5 + NdbNodeBitmask::Size );
private: private:
Uint32 blockRef; Uint32 blockRef;
Uint32 nodeId; Uint32 nodeId;
Uint32 version; // See ndb_version.h Uint32 version; // See ndb_version.h
Uint32 start_type; // As specified by cmd-line or mgm, NodeState::StartType
Uint32 latest_gci; // 0 means no fs
Uint32 skip_nodes[NdbNodeBitmask::Size]; // Nodes that does not _need_
// to be part of restart
}; };
/** /**
...@@ -59,8 +64,7 @@ private: ...@@ -59,8 +64,7 @@ private:
* The dynamic id that the node reciving this signal has * The dynamic id that the node reciving this signal has
*/ */
Uint32 dynamicId; Uint32 dynamicId;
Uint32 allNdbNodes[NdbNodeBitmask::Size];
Uint32 allNdbNodes[NdbNodeBitmask::Size];
}; };
/** /**
...@@ -73,7 +77,7 @@ class CmRegRef { ...@@ -73,7 +77,7 @@ class CmRegRef {
friend class Qmgr; friend class Qmgr;
public: public:
STATIC_CONST( SignalLength = 4 ); STATIC_CONST( SignalLength = 7 + NdbNodeBitmask::Size );
enum ErrorCode { enum ErrorCode {
ZBUSY = 0, /* Only the president can send this */ ZBUSY = 0, /* Only the president can send this */
...@@ -85,14 +89,27 @@ public: ...@@ -85,14 +89,27 @@ public:
* as president. */ * as president. */
ZNOT_PRESIDENT = 5, /* We are not president */ ZNOT_PRESIDENT = 5, /* We are not president */
ZNOT_DEAD = 6, /* We are not dead when we are starting */ ZNOT_DEAD = 6, /* We are not dead when we are starting */
ZINCOMPATIBLE_VERSION = 7 ZINCOMPATIBLE_VERSION = 7,
ZINCOMPATIBLE_START_TYPE = 8
}; };
private: private:
Uint32 blockRef; Uint32 blockRef;
Uint32 nodeId; Uint32 nodeId;
Uint32 errorCode; Uint32 errorCode;
/**
* Applicable if ZELECTION
*/
Uint32 presidentCandidate; Uint32 presidentCandidate;
Uint32 candidate_latest_gci; // 0 means non
/**
* Data for sending node sending node
*/
Uint32 latest_gci;
Uint32 start_type;
Uint32 skip_nodes[NdbNodeBitmask::Size]; // Nodes that does not _need_
// to be part of restart
}; };
class CmAdd { class CmAdd {
......
...@@ -64,6 +64,7 @@ public: ...@@ -64,6 +64,7 @@ public:
// 19 NDBFS Fipple with O_SYNC, O_CREATE etc. // 19 NDBFS Fipple with O_SYNC, O_CREATE etc.
// 20-24 BACKUP // 20-24 BACKUP
NdbcntrTestStopOnError = 25, NdbcntrTestStopOnError = 25,
NdbcntrStopNodes = 70,
// 100-105 TUP and ACC // 100-105 TUP and ACC
// 200-240 UTIL // 200-240 UTIL
// 300-305 TRIX // 300-305 TRIX
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define FAIL_REP_HPP #define FAIL_REP_HPP
#include "SignalData.hpp" #include "SignalData.hpp"
#include <NodeBitmask.hpp>
/** /**
* *
...@@ -27,6 +28,7 @@ class FailRep { ...@@ -27,6 +28,7 @@ class FailRep {
* Sender(s) & Reciver(s) * Sender(s) & Reciver(s)
*/ */
friend class Qmgr; friend class Qmgr;
friend class Ndbcntr;
/** /**
* For printing * For printing
...@@ -35,7 +37,8 @@ class FailRep { ...@@ -35,7 +37,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,
...@@ -43,13 +46,20 @@ public: ...@@ -43,13 +46,20 @@ public:
ZSTART_IN_REGREQ=3, ZSTART_IN_REGREQ=3,
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,
ZPARTITIONED_CLUSTER = 8
}; };
private: private:
Uint32 failNodeId; Uint32 failNodeId;
Uint32 failCause; Uint32 failCause;
/**
* Used when failCause == ZPARTITIONED_CLUSTER
*/
Uint32 president;
Uint32 partition[NdbNodeBitmask::Size];
}; };
......
...@@ -32,7 +32,7 @@ class StopReq ...@@ -32,7 +32,7 @@ class StopReq
friend class MgmtSrvr; friend class MgmtSrvr;
public: public:
STATIC_CONST( SignalLength = 9 ); STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
public: public:
Uint32 senderRef; Uint32 senderRef;
...@@ -49,29 +49,34 @@ public: ...@@ -49,29 +49,34 @@ public:
Int32 readOperationTimeout; // Timeout before read operations are aborted Int32 readOperationTimeout; // Timeout before read operations are aborted
Int32 operationTimeout; // Timeout before all operations are aborted Int32 operationTimeout; // Timeout before all operations are aborted
Uint32 nodes[NdbNodeBitmask::Size];
static void setSystemStop(Uint32 & requestInfo, bool value); static void setSystemStop(Uint32 & requestInfo, bool value);
static void setPerformRestart(Uint32 & requestInfo, bool value); static void setPerformRestart(Uint32 & requestInfo, bool value);
static void setNoStart(Uint32 & requestInfo, bool value); static void setNoStart(Uint32 & requestInfo, bool value);
static void setInitialStart(Uint32 & requestInfo, bool value); static void setInitialStart(Uint32 & requestInfo, bool value);
static void setEscalateOnNodeFail(Uint32 & requestInfo, bool value);
/** /**
* Don't perform "graceful" shutdown/restart... * Don't perform "graceful" shutdown/restart...
*/ */
static void setStopAbort(Uint32 & requestInfo, bool value); static void setStopAbort(Uint32 & requestInfo, bool value);
static void setStopNodes(Uint32 & requestInfo, bool value);
static bool getSystemStop(const Uint32 & requestInfo); static bool getSystemStop(const Uint32 & requestInfo);
static bool getPerformRestart(const Uint32 & requestInfo); static bool getPerformRestart(const Uint32 & requestInfo);
static bool getNoStart(const Uint32 & requestInfo); static bool getNoStart(const Uint32 & requestInfo);
static bool getInitialStart(const Uint32 & requestInfo); static bool getInitialStart(const Uint32 & requestInfo);
static bool getEscalateOnNodeFail(const Uint32 & requestInfo);
static bool getStopAbort(const Uint32 & requestInfo); static bool getStopAbort(const Uint32 & requestInfo);
static bool getStopNodes(const Uint32 & requestInfo);
}; };
struct StopConf struct StopConf
{ {
STATIC_CONST( SignalLength = 2 ); STATIC_CONST( SignalLength = 2 );
Uint32 senderData; Uint32 senderData;
Uint32 nodeState; union {
Uint32 nodeState;
Uint32 nodeId;
};
}; };
class StopRef class StopRef
...@@ -94,7 +99,9 @@ public: ...@@ -94,7 +99,9 @@ public:
NodeShutdownInProgress = 1, NodeShutdownInProgress = 1,
SystemShutdownInProgress = 2, SystemShutdownInProgress = 2,
NodeShutdownWouldCauseSystemCrash = 3, NodeShutdownWouldCauseSystemCrash = 3,
TransactionAbortFailed = 4 TransactionAbortFailed = 4,
UnsupportedNodeShutdown = 5,
MultiNodeShutdownNotMaster = 6
}; };
public: public:
...@@ -132,16 +139,16 @@ StopReq::getInitialStart(const Uint32 & requestInfo) ...@@ -132,16 +139,16 @@ StopReq::getInitialStart(const Uint32 & requestInfo)
inline inline
bool bool
StopReq::getEscalateOnNodeFail(const Uint32 & requestInfo) StopReq::getStopAbort(const Uint32 & requestInfo)
{ {
return requestInfo & 16; return requestInfo & 32;
} }
inline inline
bool bool
StopReq::getStopAbort(const Uint32 & requestInfo) StopReq::getStopNodes(const Uint32 & requestInfo)
{ {
return requestInfo & 32; return requestInfo & 64;
} }
...@@ -187,24 +194,23 @@ StopReq::setInitialStart(Uint32 & requestInfo, bool value) ...@@ -187,24 +194,23 @@ StopReq::setInitialStart(Uint32 & requestInfo, bool value)
inline inline
void void
StopReq::setEscalateOnNodeFail(Uint32 & requestInfo, bool value) StopReq::setStopAbort(Uint32 & requestInfo, bool value)
{ {
if(value) if(value)
requestInfo |= 16; requestInfo |= 32;
else else
requestInfo &= ~16; requestInfo &= ~32;
} }
inline inline
void void
StopReq::setStopAbort(Uint32 & requestInfo, bool value) StopReq::setStopNodes(Uint32 & requestInfo, bool value)
{ {
if(value) if(value)
requestInfo |= 32; requestInfo |= 64;
else else
requestInfo &= ~32; requestInfo &= ~64;
} }
#endif #endif
...@@ -46,7 +46,9 @@ public: ...@@ -46,7 +46,9 @@ public:
Complete = 1, ///< Wait for a GCP to complete Complete = 1, ///< Wait for a GCP to complete
CompleteForceStart = 2, ///< Wait for a GCP to complete start one if needed CompleteForceStart = 2, ///< Wait for a GCP to complete start one if needed
CompleteIfRunning = 3, ///< Wait for ongoing GCP CompleteIfRunning = 3, ///< Wait for ongoing GCP
CurrentGCI = 8 ///< Immediately return current GCI CurrentGCI = 8, ///< Immediately return current GCI
BlockStartGcp = 9,
UnblockStartGcp = 10
}; };
Uint32 senderRef; Uint32 senderRef;
...@@ -70,11 +72,12 @@ class WaitGCPConf { ...@@ -70,11 +72,12 @@ class WaitGCPConf {
//friend class Grep::PSCoord; //friend class Grep::PSCoord;
public: public:
STATIC_CONST( SignalLength = 2 ); STATIC_CONST( SignalLength = 3 );
public: public:
Uint32 senderData; Uint32 senderData;
Uint32 gcp; Uint32 gcp;
Uint32 blockStatus;
}; };
class WaitGCPRef { class WaitGCPRef {
......
...@@ -166,10 +166,14 @@ extern "C" { ...@@ -166,10 +166,14 @@ extern "C" {
/** NDB_MGM_EVENT_CATEGORY_BACKUP */ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
NDB_LE_BackupCompleted = 56, NDB_LE_BackupCompleted = 56,
/** NDB_MGM_EVENT_CATEGORY_BACKUP */ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
NDB_LE_BackupAborted = 57 NDB_LE_BackupAborted = 57,
/* 58 used in 5.1 */ /* 58 used in 5.1 */
/* 59 used */ /* 59 used */
/** NDB_MGM_EVENT_CATEGORY_STARTUP */
NDB_LE_StartReport = 60
/* 60 unused */ /* 60 unused */
/* 61 unused */ /* 61 unused */
/* 62 unused */ /* 62 unused */
...@@ -625,6 +629,13 @@ extern "C" { ...@@ -625,6 +629,13 @@ extern "C" {
unsigned type; unsigned type;
unsigned node_id; unsigned node_id;
} SingleUser; } SingleUser;
/** Log even data @ref NDB_LE_StartReport */
struct {
unsigned report_type;
unsigned remaining_time;
unsigned bitmask_size;
unsigned bitmask_data[1];
} StartReport;
#ifndef DOXYGEN_FIX #ifndef DOXYGEN_FIX
}; };
#else #else
......
...@@ -707,6 +707,90 @@ void getTextSingleUser(QQQQ) { ...@@ -707,6 +707,90 @@ void getTextSingleUser(QQQQ) {
} }
} }
void getTextStartReport(QQQQ) {
Uint32 time = theData[2];
Uint32 sz = theData[3];
char mask1[100];
char mask2[100];
char mask3[100];
char mask4[100];
BitmaskImpl::getText(sz, theData + 4 + (0 * sz), mask1);
BitmaskImpl::getText(sz, theData + 4 + (1 * sz), mask2);
BitmaskImpl::getText(sz, theData + 4 + (2 * sz), mask3);
BitmaskImpl::getText(sz, theData + 4 + (3 * sz), mask4);
switch(theData[1]){
case 1: // Wait initial
BaseString::snprintf
(m_text, m_text_len,
"Initial start, waiting for %s to connect, "
" nodes [ all: %s connected: %s no-wait: %s ]",
mask4, mask1, mask2, mask3);
break;
case 2: // Wait partial
BaseString::snprintf
(m_text, m_text_len,
"Waiting until nodes: %s connects, "
"nodes [ all: %s connected: %s no-wait: %s ]",
mask4, mask1, mask2, mask3);
break;
case 3: // Wait partial timeout
BaseString::snprintf
(m_text, m_text_len,
"Waiting %u sec for nodes %s to connect, "
"nodes [ all: %s connected: %s no-wait: %s ]",
time, mask4, mask1, mask2, mask3);
break;
case 4: // Wait partioned
BaseString::snprintf
(m_text, m_text_len,
"Waiting for non partitioned start, "
"nodes [ all: %s connected: %s missing: %s no-wait: %s ]",
mask1, mask2, mask4, mask3);
break;
case 5:
BaseString::snprintf
(m_text, m_text_len,
"Waiting %u sec for non partitioned start, "
"nodes [ all: %s connected: %s missing: %s no-wait: %s ]",
time, mask1, mask2, mask4, mask3);
break;
case 0x8000: // Do initial
BaseString::snprintf
(m_text, m_text_len,
"Initial start with nodes %s [ missing: %s no-wait: %s ]",
mask2, mask4, mask3);
break;
case 0x8001: // Do start
BaseString::snprintf
(m_text, m_text_len,
"Start with all nodes %s",
mask2);
break;
case 0x8002: // Do partial
BaseString::snprintf
(m_text, m_text_len,
"Start with nodes %s [ missing: %s no-wait: %s ]",
mask2, mask4, mask3);
break;
case 0x8003: // Do partioned
BaseString::snprintf
(m_text, m_text_len,
"Start potentially partitioned with nodes %s "
" [ missing: %s no-wait: %s ]",
mask2, mask4, mask3);
break;
default:
BaseString::snprintf
(m_text, m_text_len,
"Unknown startreport: 0x%x [ %s %s %s %s ]",
theData[1],
mask1, mask2, mask3, mask4);
}
}
#if 0 #if 0
BaseString::snprintf(m_text, BaseString::snprintf(m_text,
m_text_len, m_text_len,
...@@ -755,6 +839,7 @@ const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = { ...@@ -755,6 +839,7 @@ const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = {
ROW(StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO ), ROW(StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
ROW(StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO ), ROW(StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
ROW(UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO ), ROW(UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO ),
ROW(StartReport, LogLevel::llStartUp, 4, Logger::LL_INFO ),
// NODERESTART // NODERESTART
ROW(NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO ), ROW(NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
......
...@@ -134,6 +134,9 @@ Cmvmi::~Cmvmi() ...@@ -134,6 +134,9 @@ Cmvmi::~Cmvmi()
{ {
} }
#ifdef ERROR_INSERT
NodeBitmask c_error_9000_nodes_mask;
#endif
void Cmvmi::execNDB_TAMPER(Signal* signal) void Cmvmi::execNDB_TAMPER(Signal* signal)
{ {
...@@ -419,21 +422,33 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal) ...@@ -419,21 +422,33 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
const Uint32 len = signal->getLength(); const Uint32 len = signal->getLength();
if(len == 2){ if(len == 2){
globalTransporterRegistry.do_connect(tStartingNode);
globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
//----------------------------------------------------- #ifdef ERROR_INSERT
// Report that the connection to the node is opened if (! (ERROR_INSERTED(9000) && c_error_9000_nodes_mask.get(tStartingNode)))
//----------------------------------------------------- #endif
signal->theData[0] = NDB_LE_CommunicationOpened; {
signal->theData[1] = tStartingNode; globalTransporterRegistry.do_connect(tStartingNode);
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
//-----------------------------------------------------
//-----------------------------------------------------
// Report that the connection to the node is opened
//-----------------------------------------------------
signal->theData[0] = NDB_LE_CommunicationOpened;
signal->theData[1] = tStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
//-----------------------------------------------------
}
} else { } else {
for(unsigned int i = 1; i < MAX_NODES; i++ ) { for(unsigned int i = 1; i < MAX_NODES; i++ ) {
jam(); jam();
if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2){ if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2){
jam(); jam();
#ifdef ERROR_INSERT
if (ERROR_INSERTED(9000) && c_error_9000_nodes_mask.get(i))
continue;
#endif
globalTransporterRegistry.do_connect(i); globalTransporterRegistry.do_connect(i);
globalTransporterRegistry.setIOState(i, HaltIO); globalTransporterRegistry.setIOState(i, HaltIO);
...@@ -1039,7 +1054,8 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) ...@@ -1039,7 +1054,8 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
} }
DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0]; DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
if (dumpState->args[0] == DumpStateOrd::CmvmiDumpConnections){ Uint32 arg = dumpState->args[0];
if (arg == DumpStateOrd::CmvmiDumpConnections){
for(unsigned int i = 1; i < MAX_NODES; i++ ){ for(unsigned int i = 1; i < MAX_NODES; i++ ){
const char* nodeTypeStr = ""; const char* nodeTypeStr = "";
switch(getNodeInfo(i).m_type){ switch(getNodeInfo(i).m_type){
...@@ -1072,13 +1088,13 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) ...@@ -1072,13 +1088,13 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
} }
} }
if (dumpState->args[0] == DumpStateOrd::CmvmiDumpLongSignalMemory){ if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory){
infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d", infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
g_sectionSegmentPool.getSize(), g_sectionSegmentPool.getSize(),
g_sectionSegmentPool.getNoOfFree()); g_sectionSegmentPool.getNoOfFree());
} }
if (dumpState->args[0] == DumpStateOrd::CmvmiSetRestartOnErrorInsert) if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert)
{ {
if(signal->getLength() == 1) if(signal->getLength() == 1)
{ {
...@@ -1098,7 +1114,7 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) ...@@ -1098,7 +1114,7 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
} }
} }
if (dumpState->args[0] == DumpStateOrd::CmvmiTestLongSigWithDelay) { if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
unsigned i; unsigned i;
Uint32 loopCount = dumpState->args[1]; Uint32 loopCount = dumpState->args[1];
const unsigned len0 = 11; const unsigned len0 = 11;
...@@ -1126,6 +1142,30 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) ...@@ -1126,6 +1142,30 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2); sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
} }
#ifdef ERROR_INSERT
if (arg == 9000)
{
SET_ERROR_INSERT_VALUE(9000);
for (Uint32 i = 1; i<signal->getLength(); i++)
c_error_9000_nodes_mask.set(signal->theData[i]);
}
if (arg == 9001)
{
CLEAR_ERROR_INSERT_VALUE;
for (Uint32 i = 0; i<MAX_NODES; i++)
{
if (c_error_9000_nodes_mask.get(i))
{
signal->theData[0] = 0;
signal->theData[1] = i;
EXECUTE_DIRECT(CMVMI, GSN_OPEN_COMREQ, signal, 2);
}
}
c_error_9000_nodes_mask.clear();
}
#endif
#ifdef VM_TRACE #ifdef VM_TRACE
#if 0 #if 0
{ {
......
...@@ -71,6 +71,7 @@ void Dbdih::initData() ...@@ -71,6 +71,7 @@ void Dbdih::initData()
cwaitLcpSr = false; cwaitLcpSr = false;
c_blockCommit = false; c_blockCommit = false;
c_blockCommitNo = 1; c_blockCommitNo = 1;
cntrlblockref = RNIL;
}//Dbdih::initData() }//Dbdih::initData()
void Dbdih::initRecords() void Dbdih::initRecords()
......
...@@ -11659,7 +11659,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) ...@@ -11659,7 +11659,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
Uint32 tmngNode; Uint32 tmngNode;
Uint32 tmngNodeGroup; Uint32 tmngNodeGroup;
Uint32 tmngLimit; Uint32 tmngLimit;
Uint32 i; Uint32 i, j;
/**----------------------------------------------------------------------- /**-----------------------------------------------------------------------
* ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED * ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED
...@@ -11705,6 +11705,38 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) ...@@ -11705,6 +11705,38 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
Sysfile::setNodeGroup(mngNodeptr.i, SYSFILE->nodeGroups, mngNodeptr.p->nodeGroup); Sysfile::setNodeGroup(mngNodeptr.i, SYSFILE->nodeGroups, mngNodeptr.p->nodeGroup);
}//if }//if
}//for }//for
for (i = 0; i<cnoOfNodeGroups; i++)
{
jam();
bool alive = false;
NodeGroupRecordPtr NGPtr;
NGPtr.i = i;
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
for (j = 0; j<NGPtr.p->nodeCount; j++)
{
jam();
mngNodeptr.i = NGPtr.p->nodesInGroup[j];
ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord);
if (checkNodeAlive(NGPtr.p->nodesInGroup[j]))
{
alive = true;
break;
}
}
if (!alive)
{
char buf[255];
BaseString::snprintf
(buf, sizeof(buf),
"Illegal initial start, no alive node in nodegroup %u", i);
progError(__LINE__,
NDBD_EXIT_SR_RESTARTCONFLICT,
buf);
}
}
}//Dbdih::makeNodeGroups() }//Dbdih::makeNodeGroups()
/** /**
...@@ -12513,7 +12545,6 @@ void Dbdih::sendStartFragreq(Signal* signal, ...@@ -12513,7 +12545,6 @@ void Dbdih::sendStartFragreq(Signal* signal,
void Dbdih::setInitialActiveStatus() void Dbdih::setInitialActiveStatus()
{ {
NodeRecordPtr siaNodeptr; NodeRecordPtr siaNodeptr;
Uint32 tsiaNodeActiveStatus;
Uint32 tsiaNoActiveNodes; Uint32 tsiaNoActiveNodes;
tsiaNoActiveNodes = csystemnodes - cnoHotSpare; tsiaNoActiveNodes = csystemnodes - cnoHotSpare;
...@@ -12521,39 +12552,34 @@ void Dbdih::setInitialActiveStatus() ...@@ -12521,39 +12552,34 @@ void Dbdih::setInitialActiveStatus()
SYSFILE->nodeStatus[i] = 0; SYSFILE->nodeStatus[i] = 0;
for (siaNodeptr.i = 1; siaNodeptr.i < MAX_NDB_NODES; siaNodeptr.i++) { for (siaNodeptr.i = 1; siaNodeptr.i < MAX_NDB_NODES; siaNodeptr.i++) {
ptrAss(siaNodeptr, nodeRecord); ptrAss(siaNodeptr, nodeRecord);
if (siaNodeptr.p->nodeStatus == NodeRecord::ALIVE) { switch(siaNodeptr.p->nodeStatus){
case NodeRecord::ALIVE:
case NodeRecord::DEAD:
if (tsiaNoActiveNodes == 0) { if (tsiaNoActiveNodes == 0) {
jam(); jam();
siaNodeptr.p->activeStatus = Sysfile::NS_HotSpare; siaNodeptr.p->activeStatus = Sysfile::NS_HotSpare;
} else { } else {
jam(); jam();
tsiaNoActiveNodes = tsiaNoActiveNodes - 1; tsiaNoActiveNodes = tsiaNoActiveNodes - 1;
siaNodeptr.p->activeStatus = Sysfile::NS_Active; if (siaNodeptr.p->nodeStatus == NodeRecord::ALIVE)
}//if {
} else { jam();
jam(); siaNodeptr.p->activeStatus = Sysfile::NS_Active;
siaNodeptr.p->activeStatus = Sysfile::NS_NotDefined; }
}//if else
switch (siaNodeptr.p->activeStatus) { {
case Sysfile::NS_Active: siaNodeptr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
jam(); }
tsiaNodeActiveStatus = Sysfile::NS_Active; }
break;
case Sysfile::NS_HotSpare:
jam();
tsiaNodeActiveStatus = Sysfile::NS_HotSpare;
break;
case Sysfile::NS_NotDefined:
jam();
tsiaNodeActiveStatus = Sysfile::NS_NotDefined;
break; break;
default: default:
ndbrequire(false); jam();
return; siaNodeptr.p->activeStatus = Sysfile::NS_NotDefined;
break; break;
}//switch }//if
Sysfile::setNodeStatus(siaNodeptr.i, SYSFILE->nodeStatus, Sysfile::setNodeStatus(siaNodeptr.i,
tsiaNodeActiveStatus); SYSFILE->nodeStatus,
siaNodeptr.p->activeStatus);
}//for }//for
}//Dbdih::setInitialActiveStatus() }//Dbdih::setInitialActiveStatus()
...@@ -14274,11 +14300,36 @@ void Dbdih::execWAIT_GCP_REQ(Signal* signal) ...@@ -14274,11 +14300,36 @@ void Dbdih::execWAIT_GCP_REQ(Signal* signal)
jam(); jam();
conf->senderData = senderData; conf->senderData = senderData;
conf->gcp = cnewgcp; conf->gcp = cnewgcp;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB); WaitGCPConf::SignalLength, JBB);
return; return;
}//if }//if
if (requestType == WaitGCPReq::BlockStartGcp)
{
jam();
conf->senderData = senderData;
conf->gcp = cnewgcp;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB);
cgcpOrderBlocked = 1;
return;
}
if (requestType == WaitGCPReq::UnblockStartGcp)
{
jam();
conf->senderData = senderData;
conf->gcp = cnewgcp;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB);
cgcpOrderBlocked = 0;
return;
}
if(isMaster()) { if(isMaster()) {
/** /**
* Master * Master
...@@ -14290,6 +14341,7 @@ void Dbdih::execWAIT_GCP_REQ(Signal* signal) ...@@ -14290,6 +14341,7 @@ void Dbdih::execWAIT_GCP_REQ(Signal* signal)
jam(); jam();
conf->senderData = senderData; conf->senderData = senderData;
conf->gcp = coldgcp; conf->gcp = coldgcp;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB); WaitGCPConf::SignalLength, JBB);
return; return;
...@@ -14376,6 +14428,7 @@ void Dbdih::execWAIT_GCP_CONF(Signal* signal) ...@@ -14376,6 +14428,7 @@ void Dbdih::execWAIT_GCP_CONF(Signal* signal)
conf->senderData = ptr.p->clientData; conf->senderData = ptr.p->clientData;
conf->gcp = gcp; conf->gcp = gcp;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(ptr.p->clientRef, GSN_WAIT_GCP_CONF, signal, sendSignal(ptr.p->clientRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB); WaitGCPConf::SignalLength, JBB);
...@@ -14443,6 +14496,7 @@ void Dbdih::emptyWaitGCPMasterQueue(Signal* signal) ...@@ -14443,6 +14496,7 @@ void Dbdih::emptyWaitGCPMasterQueue(Signal* signal)
c_waitGCPMasterList.next(ptr); c_waitGCPMasterList.next(ptr);
conf->senderData = clientData; conf->senderData = clientData;
conf->blockStatus = cgcpOrderBlocked;
sendSignal(clientRef, GSN_WAIT_GCP_CONF, signal, sendSignal(clientRef, GSN_WAIT_GCP_CONF, signal,
WaitGCPConf::SignalLength, JBB); WaitGCPConf::SignalLength, JBB);
......
...@@ -203,6 +203,7 @@ private: ...@@ -203,6 +203,7 @@ private:
void execWAIT_GCP_CONF(Signal* signal); void execWAIT_GCP_CONF(Signal* signal);
void execSTOP_REQ(Signal* signal); void execSTOP_REQ(Signal* signal);
void execSTOP_CONF(Signal* signal);
void execRESUME_REQ(Signal* signal); void execRESUME_REQ(Signal* signal);
void execCHANGE_NODE_STATE_CONF(Signal* signal); void execCHANGE_NODE_STATE_CONF(Signal* signal);
...@@ -338,6 +339,16 @@ public: ...@@ -338,6 +339,16 @@ public:
void progError(int line, int cause, const char * extra) { void progError(int line, int cause, const char * extra) {
cntr.progError(line, cause, extra); cntr.progError(line, cause, extra);
} }
enum StopNodesStep {
SR_BLOCK_GCP_START_GCP = 0,
SR_WAIT_COMPLETE_GCP = 1,
SR_UNBLOCK_GCP_START_GCP = 2,
SR_QMGR_STOP_REQ = 3,
SR_WAIT_NODE_FAILURES = 4,
SR_CLUSTER_SHUTDOWN = 12
} m_state;
SignalCounter m_stop_req_counter;
}; };
private: private:
StopRecord c_stopRec; StopRecord c_stopRec;
......
...@@ -87,6 +87,7 @@ Ndbcntr::Ndbcntr(const class Configuration & conf): ...@@ -87,6 +87,7 @@ Ndbcntr::Ndbcntr(const class Configuration & conf):
addRecSignal(GSN_STOP_ME_CONF, &Ndbcntr::execSTOP_ME_CONF); addRecSignal(GSN_STOP_ME_CONF, &Ndbcntr::execSTOP_ME_CONF);
addRecSignal(GSN_STOP_REQ, &Ndbcntr::execSTOP_REQ); addRecSignal(GSN_STOP_REQ, &Ndbcntr::execSTOP_REQ);
addRecSignal(GSN_STOP_CONF, &Ndbcntr::execSTOP_CONF);
addRecSignal(GSN_RESUME_REQ, &Ndbcntr::execRESUME_REQ); addRecSignal(GSN_RESUME_REQ, &Ndbcntr::execRESUME_REQ);
addRecSignal(GSN_WAIT_GCP_REF, &Ndbcntr::execWAIT_GCP_REF); addRecSignal(GSN_WAIT_GCP_REF, &Ndbcntr::execWAIT_GCP_REF);
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include <signaldata/FsRemoveReq.hpp> #include <signaldata/FsRemoveReq.hpp>
#include <signaldata/ReadConfig.hpp> #include <signaldata/ReadConfig.hpp>
#include <signaldata/FailRep.hpp>
#include <AttributeHeader.hpp> #include <AttributeHeader.hpp>
#include <Configuration.hpp> #include <Configuration.hpp>
#include <DebuggerNames.hpp> #include <DebuggerNames.hpp>
...@@ -818,17 +820,9 @@ Ndbcntr::trySystemRestart(Signal* signal){ ...@@ -818,17 +820,9 @@ Ndbcntr::trySystemRestart(Signal* signal){
return false; return false;
} }
if(!allNodes && c_start.m_startPartialTimeout > now){
jam();
return false;
}
NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART; NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART;
if(c_start.m_waiting.equal(c_start.m_withoutLog)){ if(c_start.m_waiting.equal(c_start.m_withoutLog))
if(!allNodes){ {
jam();
return false;
}
jam(); jam();
srType = NodeState::ST_INITIAL_START; srType = NodeState::ST_INITIAL_START;
c_start.m_starting = c_start.m_withoutLog; // Used for starting... c_start.m_starting = c_start.m_withoutLog; // Used for starting...
...@@ -858,10 +852,6 @@ Ndbcntr::trySystemRestart(Signal* signal){ ...@@ -858,10 +852,6 @@ Ndbcntr::trySystemRestart(Signal* signal){
ndbrequire(false); // All nodes -> partitioning, which is not allowed ndbrequire(false); // All nodes -> partitioning, which is not allowed
} }
if(c_start.m_startPartitionedTimeout > now){
jam();
return false;
}
break; break;
} }
...@@ -1474,13 +1464,74 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal) ...@@ -1474,13 +1464,74 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal, sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB); 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;
}
}
}
signal->theData[0] = NDB_LE_NODE_FAILREP;
signal->theData[2] = 0;
Uint32 nodeId = 0; Uint32 nodeId = 0;
while(!allFailed.isclear()){ while(!allFailed.isclear()){
nodeId = allFailed.find(nodeId + 1); nodeId = allFailed.find(nodeId + 1);
allFailed.clear(nodeId); allFailed.clear(nodeId);
signal->theData[0] = NDB_LE_NODE_FAILREP;
signal->theData[1] = nodeId; signal->theData[1] = nodeId;
signal->theData[2] = 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}//for }//for
...@@ -1924,13 +1975,15 @@ void ...@@ -1924,13 +1975,15 @@ void
Ndbcntr::execDUMP_STATE_ORD(Signal* signal) Ndbcntr::execDUMP_STATE_ORD(Signal* signal)
{ {
DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0]; DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
if(signal->theData[0] == 13){ Uint32 arg = dumpState->args[0];
if(arg == 13){
infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d", infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d",
cstartPhase, cinternalStartphase, cndbBlocksCount); cstartPhase, cinternalStartphase, cndbBlocksCount);
infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId); infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId);
} }
if (dumpState->args[0] == DumpStateOrd::NdbcntrTestStopOnError){ if (arg == DumpStateOrd::NdbcntrTestStopOnError){
if (theConfiguration.stopOnError() == true) if (theConfiguration.stopOnError() == true)
((Configuration&)theConfiguration).stopOnError(false); ((Configuration&)theConfiguration).stopOnError(false);
...@@ -1943,6 +1996,28 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal) ...@@ -1943,6 +1996,28 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal)
SystemError::SignalLength, JBA); 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;
}
}//Ndbcntr::execDUMP_STATE_ORD() }//Ndbcntr::execDUMP_STATE_ORD()
...@@ -2003,9 +2078,12 @@ Ndbcntr::execSTOP_REQ(Signal* signal){ ...@@ -2003,9 +2078,12 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
Uint32 senderData = req->senderData; Uint32 senderData = req->senderData;
BlockReference senderRef = req->senderRef; BlockReference senderRef = req->senderRef;
bool abort = StopReq::getStopAbort(req->requestInfo); bool abort = StopReq::getStopAbort(req->requestInfo);
bool stopnodes = StopReq::getStopNodes(req->requestInfo);
if(getNodeState().startLevel < NodeState::SL_STARTED || if(!singleuser &&
abort && !singleuser){ (getNodeState().startLevel < NodeState::SL_STARTED ||
(abort && !stopnodes)))
{
/** /**
* Node is not started yet * Node is not started yet
* *
...@@ -2047,21 +2125,71 @@ Ndbcntr::execSTOP_REQ(Signal* signal){ ...@@ -2047,21 +2125,71 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
else else
ref->errorCode = StopRef::NodeShutdownInProgress; ref->errorCode = StopRef::NodeShutdownInProgress;
ref->senderData = senderData; ref->senderData = senderData;
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
if (senderRef != RNIL)
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
return;
}
if (stopnodes && !abort)
{
jam();
ref->errorCode = StopRef::UnsupportedNodeShutdown;
ref->senderData = senderData;
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;
if (senderRef != RNIL)
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
return; return;
} }
c_stopRec.stopReq = * req; c_stopRec.stopReq = * req;
c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
if(!singleuser) { if (stopnodes)
if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)) { {
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(); jam();
if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo))
{
((Configuration&)theConfiguration).stopOnError(false); ((Configuration&)theConfiguration).stopOnError(false);
} }
} }
if(!c_stopRec.checkNodeFail(signal)){ if(!c_stopRec.checkNodeFail(signal))
{
jam(); jam();
return; return;
} }
...@@ -2131,7 +2259,17 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ ...@@ -2131,7 +2259,17 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
*/ */
NodeBitmask ndbMask; NodeBitmask ndbMask;
ndbMask.assign(cntr.c_startedNodes); ndbMask.assign(cntr.c_startedNodes);
ndbMask.clear(cntr.getOwnNodeId());
if (StopReq::getStopNodes(stopReq.requestInfo))
{
NdbNodeBitmask tmp;
tmp.assign(NdbNodeBitmask::Size, stopReq.nodes);
ndbMask.bitANDC(tmp);
}
else
{
ndbMask.clear(cntr.getOwnNodeId());
}
CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0]; CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
sd->blockRef = cntr.reference(); sd->blockRef = cntr.reference();
...@@ -2153,7 +2291,8 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ ...@@ -2153,7 +2291,8 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
ref->errorCode = StopRef::NodeShutdownWouldCauseSystemCrash; ref->errorCode = StopRef::NodeShutdownWouldCauseSystemCrash;
const BlockReference bref = stopReq.senderRef; const BlockReference bref = stopReq.senderRef;
cntr.sendSignal(bref, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); if (bref != RNIL)
cntr.sendSignal(bref, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
stopReq.senderRef = 0; stopReq.senderRef = 0;
...@@ -2203,23 +2342,23 @@ Ndbcntr::StopRecord::checkTcTimeout(Signal* signal){ ...@@ -2203,23 +2342,23 @@ Ndbcntr::StopRecord::checkTcTimeout(Signal* signal){
if(stopReq.getSystemStop(stopReq.requestInfo) || stopReq.singleuser){ if(stopReq.getSystemStop(stopReq.requestInfo) || stopReq.singleuser){
jam(); jam();
if(stopReq.singleuser) if(stopReq.singleuser)
{ {
jam(); jam();
AbortAllReq * req = (AbortAllReq*)&signal->theData[0]; AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
req->senderRef = cntr.reference(); req->senderRef = cntr.reference();
req->senderData = 12; req->senderData = 12;
cntr.sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal, cntr.sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal,
AbortAllReq::SignalLength, JBB); AbortAllReq::SignalLength, JBB);
} }
else else
{ {
WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
req->senderRef = cntr.reference(); req->senderRef = cntr.reference();
req->senderData = 12; req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN;
req->requestType = WaitGCPReq::CompleteForceStart; req->requestType = WaitGCPReq::CompleteForceStart;
cntr.sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, cntr.sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
WaitGCPReq::SignalLength, JBB); WaitGCPReq::SignalLength, JBB);
} }
} else { } else {
jam(); jam();
StopPermReq * req = (StopPermReq*)&signal->theData[0]; StopPermReq * req = (StopPermReq*)&signal->theData[0];
...@@ -2381,7 +2520,7 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){ ...@@ -2381,7 +2520,7 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){
WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0]; WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
req->senderRef = reference(); req->senderRef = reference();
req->senderData = 12; req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN;
req->requestType = WaitGCPReq::CompleteForceStart; req->requestType = WaitGCPReq::CompleteForceStart;
sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
WaitGCPReq::SignalLength, JBB); WaitGCPReq::SignalLength, JBB);
...@@ -2390,29 +2529,129 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){ ...@@ -2390,29 +2529,129 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){
void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){ void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){
jamEntry(); jamEntry();
ndbrequire(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); WaitGCPConf* conf = (WaitGCPConf*)signal->getDataPtr();
NodeState newState(NodeState::SL_STOPPING_3, true);
/** switch(conf->senderData){
* Inform QMGR so that arbitrator won't kill us case StopRecord::SR_BLOCK_GCP_START_GCP:
*/ {
NodeStateRep * rep = (NodeStateRep *)&signal->theData[0]; jam();
rep->nodeState = newState; /**
rep->nodeState.masterNodeId = cmasterNodeId; *
rep->nodeState.setNodeGroup(c_nodeGroup); */
EXECUTE_DIRECT(QMGR, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength); if(!c_stopRec.checkNodeFail(signal))
{
if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ jam();
jam(); goto unblock;
StartOrd * startOrd = (StartOrd *)&signal->theData[0]; }
startOrd->restartInfo = c_stopRec.stopReq.requestInfo;
sendSignalWithDelay(CMVMI_REF, GSN_START_ORD, signal, 500, WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
StartOrd::SignalLength); req->senderRef = reference();
} else { 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(); jam();
sendSignalWithDelay(CMVMI_REF, GSN_STOP_ORD, signal, 500, 1); 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;
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;
} }
return;
} }
void Ndbcntr::execSTTORRY(Signal* signal){ void Ndbcntr::execSTTORRY(Signal* signal){
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <signaldata/CmRegSignalData.hpp> #include <signaldata/CmRegSignalData.hpp>
#include <signaldata/ApiRegSignalData.hpp> #include <signaldata/ApiRegSignalData.hpp>
#include <signaldata/FailRep.hpp> #include <signaldata/FailRep.hpp>
#include <signaldata/StopReq.hpp>
#include "timer.hpp" #include "timer.hpp"
...@@ -49,6 +50,7 @@ ...@@ -49,6 +50,7 @@
#define ZAPI_HB_HANDLING 3 #define ZAPI_HB_HANDLING 3
#define ZTIMER_HANDLING 4 #define ZTIMER_HANDLING 4
#define ZARBIT_HANDLING 5 #define ZARBIT_HANDLING 5
#define ZSTART_FAILURE_LIMIT 6
/* Error Codes ------------------------------*/ /* Error Codes ------------------------------*/
#define ZERRTOOMANY 1101 #define ZERRTOOMANY 1101
...@@ -100,18 +102,42 @@ public: ...@@ -100,18 +102,42 @@ public:
}; };
struct StartRecord { struct StartRecord {
void reset(){ m_startKey++; m_startNode = 0;} void reset(){
m_startKey++;
m_startNode = 0;
m_gsn = RNIL;
m_nodes.clearWaitingFor();
}
Uint32 m_startKey; Uint32 m_startKey;
Uint32 m_startNode; Uint32 m_startNode;
Uint64 m_startTimeout; Uint64 m_startTimeout;
Uint32 m_gsn; Uint32 m_gsn;
SignalCounter m_nodes; SignalCounter m_nodes;
} c_start; Uint32 m_latest_gci;
Uint32 m_start_type;
NdbNodeBitmask m_skip_nodes;
NdbNodeBitmask m_starting_nodes;
NdbNodeBitmask m_starting_nodes_w_log;
Uint16 m_president_candidate;
Uint32 m_president_candidate_gci;
Uint16 m_regReqReqSent;
Uint16 m_regReqReqRecv;
} c_start;
NdbNodeBitmask c_definedNodes; // DB nodes in config NdbNodeBitmask c_definedNodes; // DB nodes in config
NdbNodeBitmask c_clusterNodes; // DB nodes in cluster NdbNodeBitmask c_clusterNodes; // DB nodes in cluster
NodeBitmask c_connectedNodes; // All kinds of connected nodes NodeBitmask c_connectedNodes; // All kinds of connected nodes
/**
* Nodes which we're checking for partitioned cluster
*
* i.e. nodes that connect to use, when we already have elected president
*/
NdbNodeBitmask c_readnodes_nodes;
Uint32 c_maxDynamicId; Uint32 c_maxDynamicId;
// Records // Records
...@@ -204,6 +230,7 @@ private: ...@@ -204,6 +230,7 @@ private:
void execPRES_TOCONF(Signal* signal); void execPRES_TOCONF(Signal* signal);
void execDISCONNECT_REP(Signal* signal); void execDISCONNECT_REP(Signal* signal);
void execSYSTEM_ERROR(Signal* signal); void execSYSTEM_ERROR(Signal* signal);
void execSTOP_REQ(Signal* signal);
// Received signals // Received signals
void execDUMP_STATE_ORD(Signal* signal); void execDUMP_STATE_ORD(Signal* signal);
...@@ -218,7 +245,12 @@ private: ...@@ -218,7 +245,12 @@ 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 execDIH_RESTARTREF(Signal* signal);
void execDIH_RESTARTCONF(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);
...@@ -234,6 +266,9 @@ private: ...@@ -234,6 +266,9 @@ 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);
Uint32 check_startup(Signal* signal);
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,
...@@ -251,8 +286,9 @@ private: ...@@ -251,8 +286,9 @@ private:
// Generated statement blocks // Generated statement blocks
void startphase1(Signal* signal); void startphase1(Signal* signal);
void electionWon(); void electionWon(Signal* signal);
void cmInfoconf010Lab(Signal* signal); void cmInfoconf010Lab(Signal* signal);
void apiHbHandlingLab(Signal* signal); void apiHbHandlingLab(Signal* signal);
void timerHandlingLab(Signal* signal); void timerHandlingLab(Signal* signal);
void hbReceivedLab(Signal* signal); void hbReceivedLab(Signal* signal);
...@@ -354,12 +390,12 @@ private: ...@@ -354,12 +390,12 @@ private:
/* Status flags ----------------------------------*/ /* Status flags ----------------------------------*/
Uint32 c_restartPartialTimeout; Uint32 c_restartPartialTimeout;
Uint32 c_restartPartionedTimeout;
Uint32 c_restartFailureTimeout;
Uint64 c_start_election_time;
Uint16 creadyDistCom; Uint16 creadyDistCom;
Uint16 c_regReqReqSent;
Uint16 c_regReqReqRecv;
Uint64 c_stopElectionTime;
Uint16 cpresidentCandidate;
Uint16 cdelayRegreq; Uint16 cdelayRegreq;
Uint16 cpresidentAlive; Uint16 cpresidentAlive;
Uint16 cnoFailedNodes; Uint16 cnoFailedNodes;
...@@ -387,7 +423,9 @@ private: ...@@ -387,7 +423,9 @@ private:
Uint16 cfailedNodes[MAX_NDB_NODES]; Uint16 cfailedNodes[MAX_NDB_NODES];
Uint16 cprepFailedNodes[MAX_NDB_NODES]; Uint16 cprepFailedNodes[MAX_NDB_NODES];
Uint16 ccommitFailedNodes[MAX_NDB_NODES]; Uint16 ccommitFailedNodes[MAX_NDB_NODES];
StopReq c_stopReq;
bool check_multi_node_shutdown(Signal* signal);
}; };
#endif #endif
...@@ -35,9 +35,8 @@ void Qmgr::initData() ...@@ -35,9 +35,8 @@ void Qmgr::initData()
Uint32 hbDBAPI = 500; Uint32 hbDBAPI = 500;
setHbApiDelay(hbDBAPI); setHbApiDelay(hbDBAPI);
c_connectedNodes.clear();
c_connectedNodes.set(getOwnNodeId()); c_connectedNodes.set(getOwnNodeId());
c_stopReq.senderRef = 0;
}//Qmgr::initData() }//Qmgr::initData()
void Qmgr::initRecords() void Qmgr::initRecords()
...@@ -52,6 +51,7 @@ Qmgr::Qmgr(const class Configuration & conf) ...@@ -52,6 +51,7 @@ Qmgr::Qmgr(const class Configuration & conf)
// Transit signals // Transit signals
addRecSignal(GSN_DUMP_STATE_ORD, &Qmgr::execDUMP_STATE_ORD); addRecSignal(GSN_DUMP_STATE_ORD, &Qmgr::execDUMP_STATE_ORD);
addRecSignal(GSN_STOP_REQ, &Qmgr::execSTOP_REQ);
addRecSignal(GSN_DEBUG_SIG, &Qmgr::execDEBUG_SIG); addRecSignal(GSN_DEBUG_SIG, &Qmgr::execDEBUG_SIG);
addRecSignal(GSN_CONTINUEB, &Qmgr::execCONTINUEB); addRecSignal(GSN_CONTINUEB, &Qmgr::execCONTINUEB);
addRecSignal(GSN_CM_HEARTBEAT, &Qmgr::execCM_HEARTBEAT); addRecSignal(GSN_CM_HEARTBEAT, &Qmgr::execCM_HEARTBEAT);
...@@ -96,6 +96,12 @@ Qmgr::Qmgr(const class Configuration & conf) ...@@ -96,6 +96,12 @@ 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);
addRecSignal(GSN_DIH_RESTARTREF, &Qmgr::execDIH_RESTARTREF);
addRecSignal(GSN_DIH_RESTARTCONF, &Qmgr::execDIH_RESTARTCONF);
initData(); initData();
}//Qmgr::Qmgr() }//Qmgr::Qmgr()
......
...@@ -56,6 +56,33 @@ ...@@ -56,6 +56,33 @@
#define DEBUG_START3(signal, msg) #define DEBUG_START3(signal, msg)
#endif #endif
/**
* c_start.m_gsn = GSN_CM_REGREQ
* Possible for all nodes
* c_start.m_nodes contains all nodes in config
*
* c_start.m_gsn = GSN_CM_NODEINFOREQ;
* Set when receiving CM_REGCONF
* State possible for starting node only (not in cluster)
*
* c_start.m_nodes contains all node in alive cluster that
* that has not replied to GSN_CM_NODEINFOREQ
* passed by president in GSN_CM_REGCONF
*
* c_start.m_gsn = GSN_CM_ADD
* Possible for president only
* Set when receiving and accepting CM_REGREQ (to include node)
*
* c_start.m_nodes contains all nodes in alive cluster + starting node
* that has not replied to GSN_CM_ADD
* by sending GSN_CM_ACKADD
*
* c_start.m_gsn = GSN_CM_NODEINFOCONF
* Possible for non presidents only
* c_start.m_nodes contains a node that has been accepted by president
* but has not connected to us yet
*/
// Signal entries and statement blocks // Signal entries and statement blocks
/* 4 P R O G R A M */ /* 4 P R O G R A M */
/*******************************/ /*******************************/
...@@ -119,6 +146,30 @@ void Qmgr::execCONTINUEB(Signal* signal) ...@@ -119,6 +146,30 @@ void Qmgr::execCONTINUEB(Signal* signal)
runArbitThread(signal); runArbitThread(signal);
return; return;
break; break;
case ZSTART_FAILURE_LIMIT:{
if (cpresident != ZNIL)
{
jam();
return;
}
Uint64 now = NdbTick_CurrentMillisecond();
if (now > (c_start_election_time + c_restartFailureTimeout))
{
jam();
BaseString tmp;
tmp.append("Shutting down node as total restart time exceeds "
" StartFailureTimeout as set in config file ");
if(c_restartFailureTimeout == ~0)
tmp.append(" 0 (inifinite)");
else
tmp.appfmt(" %d", c_restartFailureTimeout);
progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR, tmp.c_str());
}
signal->theData[0] = ZSTART_FAILURE_LIMIT;
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000, 1);
return;
}
default: default:
jam(); jam();
// ZCOULD_NOT_OCCUR_ERROR; // ZCOULD_NOT_OCCUR_ERROR;
...@@ -246,14 +297,28 @@ void Qmgr::startphase1(Signal* signal) ...@@ -246,14 +297,28 @@ void Qmgr::startphase1(Signal* signal)
nodePtr.p->phase = ZSTARTING; nodePtr.p->phase = ZSTARTING;
nodePtr.p->blockRef = reference(); nodePtr.p->blockRef = reference();
c_connectedNodes.set(nodePtr.i); c_connectedNodes.set(nodePtr.i);
signal->theData[0] = reference();
sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
return;
}
signal->theData[0] = 0; // no answer void
signal->theData[1] = 0; // no id Qmgr::execDIH_RESTARTREF(Signal*signal)
signal->theData[2] = NodeInfo::DB; {
sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 3, JBB); jamEntry();
c_start.m_latest_gci = 0;
execCM_INFOCONF(signal);
}
void
Qmgr::execDIH_RESTARTCONF(Signal*signal)
{
jamEntry();
c_start.m_latest_gci = signal->theData[1];
execCM_INFOCONF(signal); execCM_INFOCONF(signal);
return;
} }
void Qmgr::setHbDelay(UintR aHbDelay) void Qmgr::setHbDelay(UintR aHbDelay)
...@@ -280,18 +345,24 @@ void Qmgr::execCONNECT_REP(Signal* signal) ...@@ -280,18 +345,24 @@ void Qmgr::execCONNECT_REP(Signal* signal)
{ {
jamEntry(); jamEntry();
const Uint32 nodeId = signal->theData[0]; const Uint32 nodeId = signal->theData[0];
if (ERROR_INSERTED(931))
{
jam();
ndbout_c("Discarding CONNECT_REP(%d)", nodeId);
infoEvent("Discarding CONNECT_REP(%d)", nodeId);
return;
}
c_connectedNodes.set(nodeId); c_connectedNodes.set(nodeId);
NodeRecPtr nodePtr; NodeRecPtr nodePtr;
nodePtr.i = getOwnNodeId(); nodePtr.i = getOwnNodeId();
ptrCheckGuard(nodePtr, MAX_NODES, nodeRec); ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
switch(nodePtr.p->phase){ switch(nodePtr.p->phase){
case ZSTARTING:
case ZRUNNING: case ZRUNNING:
ndbrequire(!c_clusterNodes.get(nodeId));
case ZSTARTING:
jam(); jam();
if(!c_start.m_nodes.isWaitingFor(nodeId)){
jam();
return;
}
break; break;
case ZPREPARE_FAIL: case ZPREPARE_FAIL:
case ZFAIL_CLOSING: case ZFAIL_CLOSING:
...@@ -303,59 +374,126 @@ void Qmgr::execCONNECT_REP(Signal* signal) ...@@ -303,59 +374,126 @@ void Qmgr::execCONNECT_REP(Signal* signal)
case ZAPI_INACTIVE: case ZAPI_INACTIVE:
return; return;
} }
if (getNodeInfo(nodeId).getType() != NodeInfo::DB)
{
jam();
return;
}
switch(c_start.m_gsn){ switch(c_start.m_gsn){
case GSN_CM_REGREQ: case GSN_CM_REGREQ:
jam(); jam();
sendCmRegReq(signal, nodeId); sendCmRegReq(signal, nodeId);
/**
* We're waiting for CM_REGCONF c_start.m_nodes contains all configured
* nodes
*/
ndbrequire(nodePtr.p->phase == ZSTARTING);
ndbrequire(c_start.m_nodes.isWaitingFor(nodeId));
return; return;
case GSN_CM_NODEINFOREQ: case GSN_CM_NODEINFOREQ:
jam(); jam();
sendCmNodeInfoReq(signal, nodeId, nodePtr.p);
if (c_start.m_nodes.isWaitingFor(nodeId))
{
jam();
ndbrequire(getOwnNodeId() != cpresident);
ndbrequire(nodePtr.p->phase == ZSTARTING);
sendCmNodeInfoReq(signal, nodeId, nodePtr.p);
return;
}
return; return;
case GSN_CM_ADD:{ case GSN_CM_NODEINFOCONF:{
jam(); jam();
ndbrequire(getOwnNodeId() != cpresident);
c_start.m_nodes.clearWaitingFor(nodeId);
c_start.m_gsn = RNIL;
NodeRecPtr addNodePtr; ndbrequire(getOwnNodeId() != cpresident);
addNodePtr.i = nodeId; ndbrequire(nodePtr.p->phase == ZRUNNING);
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec); if (c_start.m_nodes.isWaitingFor(nodeId))
cmAddPrepare(signal, addNodePtr, nodePtr.p); {
return; jam();
c_start.m_nodes.clearWaitingFor(nodeId);
c_start.m_gsn = RNIL;
NodeRecPtr addNodePtr;
addNodePtr.i = nodeId;
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
cmAddPrepare(signal, addNodePtr, nodePtr.p);
return;
}
} }
default: default:
return; (void)1;
} }
ndbrequire(!c_start.m_nodes.isWaitingFor(nodeId));
ndbrequire(!c_readnodes_nodes.get(nodeId));
c_readnodes_nodes.set(nodeId);
signal->theData[0] = reference();
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 */
/*******************************/ /*******************************/
void Qmgr::execCM_INFOCONF(Signal* signal) void Qmgr::execCM_INFOCONF(Signal* signal)
{ {
/**
* Open communcation to all DB nodes
*/
signal->theData[0] = 0; // no answer
signal->theData[1] = 0; // no id
signal->theData[2] = NodeInfo::DB;
sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 3, JBB);
cpresident = ZNIL; cpresident = ZNIL;
cpresidentCandidate = getOwnNodeId();
cpresidentAlive = ZFALSE; cpresidentAlive = ZFALSE;
c_stopElectionTime = NdbTick_CurrentMillisecond(); c_start_election_time = NdbTick_CurrentMillisecond();
c_stopElectionTime += c_restartPartialTimeout;
signal->theData[0] = ZSTART_FAILURE_LIMIT;
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000, 1);
cmInfoconf010Lab(signal); cmInfoconf010Lab(signal);
return; return;
}//Qmgr::execCM_INFOCONF() }//Qmgr::execCM_INFOCONF()
Uint32 g_start_type = 0;
NdbNodeBitmask g_nowait_nodes; // Set by clo
void Qmgr::cmInfoconf010Lab(Signal* signal) void Qmgr::cmInfoconf010Lab(Signal* signal)
{ {
c_start.m_startKey = 0; c_start.m_startKey = 0;
c_start.m_startNode = getOwnNodeId(); c_start.m_startNode = getOwnNodeId();
c_start.m_nodes.clearWaitingFor(); c_start.m_nodes.clearWaitingFor();
c_start.m_gsn = GSN_CM_REGREQ; c_start.m_gsn = GSN_CM_REGREQ;
c_start.m_starting_nodes.clear();
c_start.m_starting_nodes_w_log.clear();
c_start.m_regReqReqSent = 0;
c_start.m_regReqReqRecv = 0;
c_start.m_skip_nodes = g_nowait_nodes;
c_start.m_skip_nodes.bitAND(c_definedNodes);
c_start.m_start_type = g_start_type;
NodeRecPtr nodePtr; NodeRecPtr nodePtr;
c_regReqReqSent = c_regReqReqRecv = 0;
cnoOfNodes = 0; cnoOfNodes = 0;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam(); jam();
...@@ -390,14 +528,18 @@ void Qmgr::cmInfoconf010Lab(Signal* signal) ...@@ -390,14 +528,18 @@ void Qmgr::cmInfoconf010Lab(Signal* signal)
void void
Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){ Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
c_regReqReqSent++; CmRegReq * req = (CmRegReq *)&signal->theData[0];
CmRegReq * const cmRegReq = (CmRegReq *)&signal->theData[0]; req->blockRef = reference();
cmRegReq->blockRef = reference(); req->nodeId = getOwnNodeId();
cmRegReq->nodeId = getOwnNodeId(); req->version = NDB_VERSION;
cmRegReq->version = NDB_VERSION; req->latest_gci = c_start.m_latest_gci;
req->start_type = c_start.m_start_type;
c_start.m_skip_nodes.copyto(NdbNodeBitmask::Size, req->skip_nodes);
const Uint32 ref = calcQmgrBlockRef(nodeId); const Uint32 ref = calcQmgrBlockRef(nodeId);
sendSignal(ref, GSN_CM_REGREQ, signal, CmRegReq::SignalLength, JBB); sendSignal(ref, GSN_CM_REGREQ, signal, CmRegReq::SignalLength, JBB);
DEBUG_START(GSN_CM_REGREQ, nodeId, ""); DEBUG_START(GSN_CM_REGREQ, nodeId, "");
c_start.m_regReqReqSent++;
} }
/* /*
...@@ -437,6 +579,18 @@ Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){ ...@@ -437,6 +579,18 @@ Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
/*******************************/ /*******************************/
/* CM_REGREQ */ /* CM_REGREQ */
/*******************************/ /*******************************/
static
int
check_start_type(Uint32 starting, Uint32 own)
{
if (starting == (1 << NodeState::ST_INITIAL_START) &&
((own & (1 << NodeState::ST_INITIAL_START)) == 0))
{
return 1;
}
return 0;
}
void Qmgr::execCM_REGREQ(Signal* signal) void Qmgr::execCM_REGREQ(Signal* signal)
{ {
DEBUG_START3(signal, ""); DEBUG_START3(signal, "");
...@@ -448,6 +602,17 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -448,6 +602,17 @@ void Qmgr::execCM_REGREQ(Signal* signal)
const BlockReference Tblockref = cmRegReq->blockRef; const BlockReference Tblockref = cmRegReq->blockRef;
const Uint32 startingVersion = cmRegReq->version; const Uint32 startingVersion = cmRegReq->version;
addNodePtr.i = cmRegReq->nodeId; addNodePtr.i = cmRegReq->nodeId;
Uint32 gci = 1;
Uint32 start_type = ~0;
NdbNodeBitmask skip_nodes;
if (signal->getLength() == CmRegReq::SignalLength)
{
jam();
gci = cmRegReq->latest_gci;
start_type = cmRegReq->start_type;
skip_nodes.assign(NdbNodeBitmask::Size, cmRegReq->skip_nodes);
}
if (creadyDistCom == ZFALSE) { if (creadyDistCom == ZFALSE) {
jam(); jam();
...@@ -461,11 +626,19 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -461,11 +626,19 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return; return;
} }
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec); if (check_start_type(start_type, c_start.m_start_type))
{
if (cpresident != getOwnNodeId()){ jam();
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZINCOMPATIBLE_START_TYPE);
return;
}
if (cpresident != getOwnNodeId())
{
jam(); jam();
if (cpresident == ZNIL) {
if (cpresident == ZNIL)
{
/*** /***
* We don't know the president. * We don't know the president.
* If the node to be added has lower node id * If the node to be added has lower node id
...@@ -473,13 +646,18 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -473,13 +646,18 @@ void Qmgr::execCM_REGREQ(Signal* signal)
* candidate * candidate
*/ */
jam(); jam();
if (addNodePtr.i < cpresidentCandidate) { if (gci > c_start.m_president_candidate_gci ||
(gci == c_start.m_president_candidate_gci &&
addNodePtr.i < c_start.m_president_candidate))
{
jam(); jam();
cpresidentCandidate = addNodePtr.i; c_start.m_president_candidate = addNodePtr.i;
}//if c_start.m_president_candidate_gci = gci;
}
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZELECTION); sendCmRegrefLab(signal, Tblockref, CmRegRef::ZELECTION);
return; return;
} }
/** /**
* We are not the president. * We are not the president.
* We know the president. * We know the president.
...@@ -489,7 +667,8 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -489,7 +667,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return; return;
}//if }//if
if (c_start.m_startNode != 0){ if (c_start.m_startNode != 0)
{
jam(); jam();
/** /**
* President busy by adding another node * President busy by adding another node
...@@ -498,7 +677,8 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -498,7 +677,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return; return;
}//if }//if
if (ctoStatus == Q_ACTIVE) { if (ctoStatus == Q_ACTIVE)
{
jam(); jam();
/** /**
* Active taking over as president * Active taking over as president
...@@ -507,7 +687,8 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -507,7 +687,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return; return;
}//if }//if
if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB) { if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB)
{
jam(); jam();
/** /**
* The new node is not in config file * The new node is not in config file
...@@ -516,13 +697,15 @@ void Qmgr::execCM_REGREQ(Signal* signal) ...@@ -516,13 +697,15 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return; return;
} }
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
Phase phase = addNodePtr.p->phase; Phase phase = addNodePtr.p->phase;
if (phase != ZINIT){ if (phase != ZINIT)
{
jam(); jam();
DEBUG("phase = " << phase); DEBUG("phase = " << phase);
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_DEAD); sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_DEAD);
return; return;
}//if }
jam(); jam();
/** /**
...@@ -594,7 +777,12 @@ void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef, ...@@ -594,7 +777,12 @@ void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef,
ref->blockRef = reference(); ref->blockRef = reference();
ref->nodeId = getOwnNodeId(); ref->nodeId = getOwnNodeId();
ref->errorCode = Terror; ref->errorCode = Terror;
ref->presidentCandidate = (cpresident == ZNIL ? cpresidentCandidate : cpresident); ref->presidentCandidate =
(cpresident == ZNIL ? c_start.m_president_candidate : cpresident);
ref->candidate_latest_gci = c_start.m_president_candidate_gci;
ref->latest_gci = c_start.m_latest_gci;
ref->start_type = c_start.m_start_type;
c_start.m_skip_nodes.copyto(NdbNodeBitmask::Size, ref->skip_nodes);
sendSignal(TBRef, GSN_CM_REGREF, signal, sendSignal(TBRef, GSN_CM_REGREF, signal,
CmRegRef::SignalLength, JBB); CmRegRef::SignalLength, JBB);
DEBUG_START(GSN_CM_REGREF, refToNode(TBRef), ""); DEBUG_START(GSN_CM_REGREF, refToNode(TBRef), "");
...@@ -622,22 +810,33 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -622,22 +810,33 @@ void Qmgr::execCM_REGCONF(Signal* signal)
jamEntry(); jamEntry();
const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0]; const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
Uint32 presidentNodeId = cmRegConf->presidentNodeId;
if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) { if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) {
jam(); jam();
char buf[128]; char buf[128];
BaseString::snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion); BaseString::snprintf(buf,sizeof(buf),
"incompatible version own=0x%x other=0x%x, "
" shutting down",
NDB_VERSION, cmRegConf->presidentVersion);
systemErrorLab(signal, __LINE__, buf); systemErrorLab(signal, __LINE__, buf);
return; return;
} }
myNodePtr.i = getOwnNodeId();
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
ndbrequire(c_start.m_gsn == GSN_CM_REGREQ);
ndbrequire(myNodePtr.p->phase = ZSTARTING);
cpdistref = cmRegConf->presidentBlockRef; cpdistref = cmRegConf->presidentBlockRef;
cpresident = cmRegConf->presidentNodeId; cpresident = cmRegConf->presidentNodeId;
UintR TdynamicId = cmRegConf->dynamicId; UintR TdynamicId = cmRegConf->dynamicId;
c_maxDynamicId = TdynamicId; c_maxDynamicId = TdynamicId;
c_clusterNodes.assign(NdbNodeBitmask::Size, cmRegConf->allNdbNodes); c_clusterNodes.assign(NdbNodeBitmask::Size, cmRegConf->allNdbNodes);
myNodePtr.p->ndynamicId = TdynamicId;
/*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/
// Send this as an EVENT REPORT to inform about hearing about // Send this as an EVENT REPORT to inform about hearing about
// other NDB node proclaiming to be president. // other NDB node proclaiming to be president.
...@@ -648,10 +847,6 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -648,10 +847,6 @@ void Qmgr::execCM_REGCONF(Signal* signal)
signal->theData[3] = TdynamicId; signal->theData[3] = TdynamicId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
myNodePtr.i = getOwnNodeId();
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
myNodePtr.p->ndynamicId = TdynamicId;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam(); jam();
if (c_clusterNodes.get(nodePtr.i)){ if (c_clusterNodes.get(nodePtr.i)){
...@@ -674,6 +869,84 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -674,6 +869,84 @@ void Qmgr::execCM_REGCONF(Signal* signal)
return; return;
}//Qmgr::execCM_REGCONF() }//Qmgr::execCM_REGCONF()
void
Qmgr::check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn)
{
NodeRecPtr myNodePtr;
myNodePtr.i = getOwnNodeId();
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
NodeRecPtr nodePtr;
nodePtr.i = nodeId;
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
ndbrequire(c_readnodes_nodes.get(nodeId));
ReadNodesConf* conf = (ReadNodesConf*)signal->getDataPtr();
if (gsn == GSN_READ_NODESREF)
{
jam();
retry:
signal->theData[0] = reference();
sendSignal(calcQmgrBlockRef(nodeId), GSN_READ_NODESREQ, signal, 1, JBA);
return;
}
if (conf->masterNodeId == ZNIL)
{
jam();
goto retry;
}
Uint32 president = conf->masterNodeId;
if (president == cpresident)
{
jam();
c_readnodes_nodes.clear(nodeId);
return;
}
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);
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);
progError(__LINE__,
NDBD_EXIT_ARBIT_SHUTDOWN,
buf);
ndbrequire(false);
}
void void
Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){ Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){
CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtrSend(); CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtrSend();
...@@ -703,26 +976,105 @@ Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){ ...@@ -703,26 +976,105 @@ Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){
/*******************************/ /*******************************/
/* CM_REGREF */ /* CM_REGREF */
/*******************************/ /*******************************/
static
const char *
get_start_type_string(Uint32 st)
{
static char buf[256];
if (st == 0)
{
return "<ANY>";
}
else
{
buf[0] = 0;
for(Uint32 i = 0; i<NodeState::ST_ILLEGAL_TYPE; i++)
{
if (st & (1 << i))
{
if (buf[0])
strcat(buf, "/");
switch(i){
case NodeState::ST_INITIAL_START:
strcat(buf, "inital start");
break;
case NodeState::ST_SYSTEM_RESTART:
strcat(buf, "system restart");
break;
case NodeState::ST_NODE_RESTART:
strcat(buf, "node restart");
break;
case NodeState::ST_INITIAL_NODE_RESTART:
strcat(buf, "initial node restart");
break;
}
}
}
return buf;
}
}
void Qmgr::execCM_REGREF(Signal* signal) void Qmgr::execCM_REGREF(Signal* signal)
{ {
jamEntry(); jamEntry();
c_regReqReqRecv++;
// Ignore block reference in data[0] CmRegRef* ref = (CmRegRef*)signal->getDataPtr();
UintR TaddNodeno = signal->theData[1]; UintR TaddNodeno = ref->nodeId;
UintR TrefuseReason = signal->theData[2]; UintR TrefuseReason = ref->errorCode;
Uint32 candidate = signal->theData[3]; Uint32 candidate = ref->presidentCandidate;
Uint32 node_gci = 1;
Uint32 candidate_gci = 1;
Uint32 start_type = ~0;
NdbNodeBitmask skip_nodes;
DEBUG_START3(signal, TrefuseReason); DEBUG_START3(signal, TrefuseReason);
if(candidate != cpresidentCandidate){ if (signal->getLength() == CmRegRef::SignalLength)
{
jam(); jam();
c_regReqReqRecv = ~0; node_gci = ref->latest_gci;
candidate_gci = ref->candidate_latest_gci;
start_type = ref->start_type;
skip_nodes.assign(NdbNodeBitmask::Size, ref->skip_nodes);
} }
c_start.m_regReqReqRecv++;
// Ignore block reference in data[0]
if(candidate != c_start.m_president_candidate)
{
jam();
c_start.m_regReqReqRecv = ~0;
}
c_start.m_starting_nodes.set(TaddNodeno);
if (node_gci)
{
jam();
c_start.m_starting_nodes_w_log.set(TaddNodeno);
}
skip_nodes.bitAND(c_definedNodes);
c_start.m_skip_nodes.bitOR(skip_nodes);
char buf[100];
switch (TrefuseReason) { switch (TrefuseReason) {
case CmRegRef::ZINCOMPATIBLE_VERSION: case CmRegRef::ZINCOMPATIBLE_VERSION:
jam(); jam();
systemErrorLab(signal, __LINE__, "incompatible version, connection refused by running ndb node"); systemErrorLab(signal, __LINE__,
"incompatible version, "
"connection refused by running ndb node");
case CmRegRef::ZINCOMPATIBLE_START_TYPE:
jam();
BaseString::snprintf(buf, sizeof(buf),
"incompatible start type detected: node %d"
" reports %s(%d) my start type: %s(%d)",
TaddNodeno,
get_start_type_string(start_type), start_type,
get_start_type_string(c_start.m_start_type),
c_start.m_start_type);
progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf);
break; break;
case CmRegRef::ZBUSY: case CmRegRef::ZBUSY:
case CmRegRef::ZBUSY_TO_PRES: case CmRegRef::ZBUSY_TO_PRES:
...@@ -741,14 +1093,18 @@ void Qmgr::execCM_REGREF(Signal* signal) ...@@ -741,14 +1093,18 @@ void Qmgr::execCM_REGREF(Signal* signal)
break; break;
case CmRegRef::ZELECTION: case CmRegRef::ZELECTION:
jam(); jam();
if (cpresidentCandidate > TaddNodeno) { if (candidate_gci > c_start.m_president_candidate_gci ||
(candidate_gci == c_start.m_president_candidate_gci &&
candidate < c_start.m_president_candidate))
{
jam(); jam();
//---------------------------------------- //----------------------------------------
/* We may already have a candidate */ /* We may already have a candidate */
/* choose the lowest nodeno */ /* choose the lowest nodeno */
//---------------------------------------- //----------------------------------------
signal->theData[3] = 2; signal->theData[3] = 2;
cpresidentCandidate = TaddNodeno; c_start.m_president_candidate = candidate;
c_start.m_president_candidate_gci = candidate_gci;
} else { } else {
signal->theData[3] = 4; signal->theData[3] = 4;
}//if }//if
...@@ -776,32 +1132,34 @@ void Qmgr::execCM_REGREF(Signal* signal) ...@@ -776,32 +1132,34 @@ void Qmgr::execCM_REGREF(Signal* signal)
//----------------------------------------- //-----------------------------------------
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
if(cpresidentAlive == ZTRUE){ if(cpresidentAlive == ZTRUE)
{
jam(); jam();
DEBUG(""); DEBUG("cpresidentAlive");
return; return;
} }
if(c_regReqReqSent != c_regReqReqRecv){ if(c_start.m_regReqReqSent != c_start.m_regReqReqRecv)
{
jam(); jam();
DEBUG( c_regReqReqSent << " != " << c_regReqReqRecv); DEBUG(c_start.m_regReqReqSent << " != " << c_start.m_regReqReqRecv);
return; return;
} }
if(cpresidentCandidate != getOwnNodeId()){ if(c_start.m_president_candidate != getOwnNodeId())
{
jam(); jam();
DEBUG(""); DEBUG("i'm not the candidate");
return; return;
} }
/** /**
* All configured nodes has agreed * All connected nodes has agreed
*/ */
Uint64 now = NdbTick_CurrentMillisecond(); if(check_startup(signal))
if((c_regReqReqRecv == cnoOfNodes) || now > c_stopElectionTime){ {
jam(); jam();
electionWon(); electionWon(signal);
sendSttorryLab(signal);
/** /**
* Start timer handling * Start timer handling
...@@ -813,8 +1171,192 @@ void Qmgr::execCM_REGREF(Signal* signal) ...@@ -813,8 +1171,192 @@ void Qmgr::execCM_REGREF(Signal* signal)
return; return;
}//Qmgr::execCM_REGREF() }//Qmgr::execCM_REGREF()
Uint32
Qmgr::check_startup(Signal* signal)
{
Uint64 now = NdbTick_CurrentMillisecond();
Uint64 partial_timeout = c_start_election_time + c_restartPartialTimeout;
Uint64 partitioned_timeout = partial_timeout + c_restartPartionedTimeout;
/**
* First see if we should wait more...
*/
NdbNodeBitmask tmp;
tmp.bitOR(c_start.m_skip_nodes);
tmp.bitOR(c_start.m_starting_nodes);
NdbNodeBitmask wait;
wait.assign(c_definedNodes);
wait.bitANDC(tmp);
Uint32 retVal = 0;
NdbNodeBitmask report_mask;
if ((c_start.m_latest_gci == 0) ||
(c_start.m_start_type == (1 << NodeState::ST_INITIAL_START)))
{
if (!tmp.equal(c_definedNodes))
{
jam();
signal->theData[1] = 1;
signal->theData[2] = ~0;
report_mask.assign(wait);
retVal = 0;
goto start_report;
}
else
{
jam();
signal->theData[1] = 0x8000;
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
retVal = 1;
goto start_report;
}
}
const bool all = c_start.m_starting_nodes.equal(c_definedNodes);
CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
{
/**
* Check for missing node group directly
*/
char buf[100];
NdbNodeBitmask check;
check.assign(c_definedNodes);
check.bitANDC(c_start.m_starting_nodes); // Not connected nodes
check.bitOR(c_start.m_starting_nodes_w_log);
sd->blockRef = reference();
sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
sd->mask = check;
EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
CheckNodeGroups::SignalLength);
if (sd->output == CheckNodeGroups::Lose)
{
jam();
goto missing_nodegroup;
}
}
sd->blockRef = reference();
sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
sd->mask = c_start.m_starting_nodes;
EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
CheckNodeGroups::SignalLength);
const Uint32 result = sd->output;
sd->blockRef = reference();
sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
sd->mask = c_start.m_starting_nodes_w_log;
EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
CheckNodeGroups::SignalLength);
const Uint32 result_w_log = sd->output;
if (tmp.equal(c_definedNodes))
{
/**
* All nodes (wrt no-wait nodes) has connected...
* this means that we will now start or die
*/
jam();
switch(result_w_log){
case CheckNodeGroups::Lose:
{
jam();
goto missing_nodegroup;
}
case CheckNodeGroups::Win:
signal->theData[1] = all ? 0x8001 : 0x8002;
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
retVal = 1;
goto start_report;
case CheckNodeGroups::Partitioning:
ndbrequire(result != CheckNodeGroups::Lose);
signal->theData[1] =
all ? 0x8001 : (result == CheckNodeGroups::Win ? 0x8002 : 0x8003);
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
retVal = 1;
goto start_report;
}
}
if (now < partial_timeout)
{
jam();
signal->theData[1] = c_restartPartialTimeout == ~0 ? 2 : 3;
signal->theData[2] = Uint32((partial_timeout - now + 500) / 1000);
report_mask.assign(wait);
retVal = 0;
goto start_report;
}
/**
* Start partial has passed...check for partitioning...
*/
switch(result_w_log){
case CheckNodeGroups::Lose:
jam();
goto missing_nodegroup;
case CheckNodeGroups::Partitioning:
if (now < partitioned_timeout && result != CheckNodeGroups::Win)
{
signal->theData[1] = c_restartPartionedTimeout == ~0 ? 4 : 5;
signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000);
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
retVal = 0;
goto start_report;
}
// Fall through...
case CheckNodeGroups::Win:
signal->theData[1] =
all ? 0x8001 : (result == CheckNodeGroups::Win ? 0x8002 : 0x8003);
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
retVal = 1;
goto start_report;
}
ndbrequire(false);
start_report:
jam();
{
Uint32 sz = NdbNodeBitmask::Size;
signal->theData[0] = NDB_LE_StartReport;
signal->theData[3] = sz;
Uint32* ptr = signal->theData+4;
c_definedNodes.copyto(sz, ptr); ptr += sz;
c_start.m_starting_nodes.copyto(sz, ptr); ptr += sz;
c_start.m_skip_nodes.copyto(sz, ptr); ptr += sz;
report_mask.copyto(sz, ptr); ptr+= sz;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal,
4+4*NdbNodeBitmask::Size, JBB);
}
return retVal;
missing_nodegroup:
jam();
char buf[100], mask1[100], mask2[100];
c_start.m_starting_nodes.getText(mask1);
tmp.assign(c_start.m_starting_nodes);
tmp.bitANDC(c_start.m_starting_nodes_w_log);
tmp.getText(mask2);
BaseString::snprintf(buf, sizeof(buf),
"Unable to start missing node group! "
" starting: %s (missing fs for: %s)",
mask1, mask2);
progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf);
}
void void
Qmgr::electionWon(){ Qmgr::electionWon(Signal* signal){
NodeRecPtr myNodePtr; NodeRecPtr myNodePtr;
cpresident = getOwnNodeId(); /* This node becomes president. */ cpresident = getOwnNodeId(); /* This node becomes president. */
myNodePtr.i = getOwnNodeId(); myNodePtr.i = getOwnNodeId();
...@@ -831,8 +1373,21 @@ Qmgr::electionWon(){ ...@@ -831,8 +1373,21 @@ Qmgr::electionWon(){
c_clusterNodes.set(getOwnNodeId()); c_clusterNodes.set(getOwnNodeId());
cpresidentAlive = ZTRUE; cpresidentAlive = ZTRUE;
c_stopElectionTime = ~0; c_start_election_time = ~0;
c_start.reset(); c_start.reset();
signal->theData[0] = NDB_LE_CM_REGCONF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cpresident;
signal->theData[3] = 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
c_start.m_starting_nodes.clear(getOwnNodeId());
if (c_start.m_starting_nodes.isclear())
{
jam();
sendSttorryLab(signal);
}
} }
/* /*
...@@ -846,7 +1401,14 @@ Qmgr::electionWon(){ ...@@ -846,7 +1401,14 @@ Qmgr::electionWon(){
/*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/
void Qmgr::regreqTimeLimitLab(Signal* signal) void Qmgr::regreqTimeLimitLab(Signal* signal)
{ {
if(cpresident == ZNIL){ if(cpresident == ZNIL)
{
if (c_start.m_president_candidate == ZNIL)
{
jam();
c_start.m_president_candidate = getOwnNodeId();
}
cmInfoconf010Lab(signal); cmInfoconf010Lab(signal);
} }
}//Qmgr::regreqTimelimitLab() }//Qmgr::regreqTimelimitLab()
...@@ -967,7 +1529,7 @@ Qmgr::cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec * self){ ...@@ -967,7 +1529,7 @@ Qmgr::cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec * self){
ndbrequire(signal->header.theVerId_signalNumber == GSN_CM_ADD); ndbrequire(signal->header.theVerId_signalNumber == GSN_CM_ADD);
c_start.m_nodes.clearWaitingFor(); c_start.m_nodes.clearWaitingFor();
c_start.m_nodes.setWaitingFor(nodePtr.i); c_start.m_nodes.setWaitingFor(nodePtr.i);
c_start.m_gsn = GSN_CM_ADD; c_start.m_gsn = GSN_CM_NODEINFOCONF;
#else #else
warningEvent("Enabling communication to CM_ADD node %u state=%d", warningEvent("Enabling communication to CM_ADD node %u state=%d",
nodePtr.i, nodePtr.i,
...@@ -1256,6 +1818,17 @@ void Qmgr::execCM_ACKADD(Signal* signal) ...@@ -1256,6 +1818,17 @@ void Qmgr::execCM_ACKADD(Signal* signal)
*/ */
handleArbitNdbAdd(signal, addNodePtr.i); handleArbitNdbAdd(signal, addNodePtr.i);
c_start.reset(); c_start.reset();
if (c_start.m_starting_nodes.get(addNodePtr.i))
{
jam();
c_start.m_starting_nodes.clear(addNodePtr.i);
if (c_start.m_starting_nodes.isclear())
{
jam();
sendSttorryLab(signal);
}
}
return; return;
}//switch }//switch
ndbrequire(false); ndbrequire(false);
...@@ -1409,7 +1982,8 @@ void Qmgr::initData(Signal* signal) ...@@ -1409,7 +1982,8 @@ void Qmgr::initData(Signal* signal)
cnoPrepFailedNodes = 0; cnoPrepFailedNodes = 0;
creadyDistCom = ZFALSE; creadyDistCom = ZFALSE;
cpresident = ZNIL; cpresident = ZNIL;
cpresidentCandidate = ZNIL; c_start.m_president_candidate = ZNIL;
c_start.m_president_candidate_gci = 0;
cpdistref = 0; cpdistref = 0;
cneighbourh = ZNIL; cneighbourh = ZNIL;
cneighbourl = ZNIL; cneighbourl = ZNIL;
...@@ -1437,15 +2011,33 @@ void Qmgr::initData(Signal* signal) ...@@ -1437,15 +2011,33 @@ void Qmgr::initData(Signal* signal)
Uint32 hbDBAPI = 1500; Uint32 hbDBAPI = 1500;
Uint32 arbitTimeout = 1000; Uint32 arbitTimeout = 1000;
c_restartPartialTimeout = 30000; c_restartPartialTimeout = 30000;
c_restartPartionedTimeout = 60000;
c_restartFailureTimeout = ~0;
ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &hbDBDB); ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &hbDBDB);
ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL, &hbDBAPI); ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL, &hbDBAPI);
ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_TIMEOUT, &arbitTimeout); ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_TIMEOUT, &arbitTimeout);
ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT, ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT,
&c_restartPartialTimeout); &c_restartPartialTimeout);
if(c_restartPartialTimeout == 0){ ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT,
&c_restartPartionedTimeout);
ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT,
&c_restartFailureTimeout);
if(c_restartPartialTimeout == 0)
{
c_restartPartialTimeout = ~0; c_restartPartialTimeout = ~0;
} }
if (c_restartPartionedTimeout ==0)
{
c_restartPartionedTimeout = ~0;
}
if (c_restartFailureTimeout == 0)
{
c_restartFailureTimeout = ~0;
}
setHbDelay(hbDBDB); setHbDelay(hbDBDB);
setHbApiDelay(hbDBAPI); setHbApiDelay(hbDBAPI);
setArbitTimeout(arbitTimeout); setArbitTimeout(arbitTimeout);
...@@ -1872,10 +2464,23 @@ void Qmgr::execDISCONNECT_REP(Signal* signal) ...@@ -1872,10 +2464,23 @@ void Qmgr::execDISCONNECT_REP(Signal* signal)
const Uint32 nodeId = rep->nodeId; const Uint32 nodeId = rep->nodeId;
const Uint32 err = rep->err; const Uint32 err = rep->err;
c_connectedNodes.clear(nodeId); c_connectedNodes.clear(nodeId);
c_readnodes_nodes.clear(nodeId);
NodeRecPtr nodePtr; NodeRecPtr nodePtr;
nodePtr.i = getOwnNodeId(); nodePtr.i = getOwnNodeId();
ptrCheckGuard(nodePtr, MAX_NODES, nodeRec); ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
char buf[100];
if (getNodeInfo(nodeId).getType() == NodeInfo::DB &&
getNodeState().startLevel < NodeState::SL_STARTED)
{
jam();
CRASH_INSERTION(932);
BaseString::snprintf(buf, 100, "Node %u disconected", nodeId);
progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
ndbrequire(false);
}
switch(nodePtr.p->phase){ switch(nodePtr.p->phase){
case ZRUNNING: case ZRUNNING:
jam(); jam();
...@@ -1893,9 +2498,12 @@ void Qmgr::execDISCONNECT_REP(Signal* signal) ...@@ -1893,9 +2498,12 @@ void Qmgr::execDISCONNECT_REP(Signal* signal)
case ZAPI_ACTIVE: case ZAPI_ACTIVE:
ndbrequire(false); ndbrequire(false);
case ZAPI_INACTIVE: case ZAPI_INACTIVE:
{
BaseString::snprintf(buf, 100, "Node %u disconected", nodeId);
progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
ndbrequire(false); ndbrequire(false);
} }
}
node_failed(signal, nodeId); node_failed(signal, nodeId);
}//DISCONNECT_REP }//DISCONNECT_REP
...@@ -2150,10 +2758,20 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2150,10 +2758,20 @@ 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();
if (check_multi_node_shutdown(signal))
{
jam();
return;
}
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";
...@@ -2174,17 +2792,51 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2174,17 +2792,51 @@ 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 = NDBD_EXIT_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;
}
case FailRep::ZMULTI_NODE_SHUTDOWN:
msg = "Multi node shutdown";
break;
default:
msg = "<UNKNOWN>";
} }
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, msg ? msg : "<Unknown>",
msg ? msg : "<Unknown>"); aFailCause);
progError(__LINE__, 0, buf); progError(__LINE__, code, buf);
return; return;
}//if }//if
...@@ -2241,7 +2893,13 @@ void Qmgr::execPREP_FAILREQ(Signal* signal) ...@@ -2241,7 +2893,13 @@ void Qmgr::execPREP_FAILREQ(Signal* signal)
{ {
NodeRecPtr myNodePtr; NodeRecPtr myNodePtr;
jamEntry(); jamEntry();
if (check_multi_node_shutdown(signal))
{
jam();
return;
}
PrepFailReqRef * const prepFail = (PrepFailReqRef *)&signal->theData[0]; PrepFailReqRef * const prepFail = (PrepFailReqRef *)&signal->theData[0];
BlockReference Tblockref = prepFail->xxxBlockRef; BlockReference Tblockref = prepFail->xxxBlockRef;
...@@ -3893,6 +4551,7 @@ Qmgr::stateArbitCrash(Signal* signal) ...@@ -3893,6 +4551,7 @@ Qmgr::stateArbitCrash(Signal* signal)
if (! (arbitRec.getTimediff() > getArbitTimeout())) if (! (arbitRec.getTimediff() > getArbitTimeout()))
return; return;
#endif #endif
CRASH_INSERTION(932);
progError(__LINE__, NDBD_EXIT_ARBIT_SHUTDOWN, progError(__LINE__, NDBD_EXIT_ARBIT_SHUTDOWN,
"Arbitrator decided to shutdown this node"); "Arbitrator decided to shutdown this node");
} }
...@@ -3956,8 +4615,10 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal) ...@@ -3956,8 +4615,10 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
case 1: case 1:
infoEvent("creadyDistCom = %d, cpresident = %d\n", infoEvent("creadyDistCom = %d, cpresident = %d\n",
creadyDistCom, cpresident); creadyDistCom, cpresident);
infoEvent("cpresidentAlive = %d, cpresidentCand = %d\n", infoEvent("cpresidentAlive = %d, cpresidentCand = %d (gci: %d)\n",
cpresidentAlive, cpresidentCandidate); cpresidentAlive,
c_start.m_president_candidate,
c_start.m_president_candidate_gci);
infoEvent("ctoStatus = %d\n", ctoStatus); infoEvent("ctoStatus = %d\n", ctoStatus);
for(Uint32 i = 1; i<MAX_NDB_NODES; i++){ for(Uint32 i = 1; i<MAX_NDB_NODES; i++){
if(getNodeInfo(i).getType() == NodeInfo::DB){ if(getNodeInfo(i).getType() == NodeInfo::DB){
...@@ -4054,3 +4715,42 @@ Qmgr::execAPI_BROADCAST_REP(Signal* signal) ...@@ -4054,3 +4715,42 @@ Qmgr::execAPI_BROADCAST_REP(Signal* signal)
NodeReceiverGroup rg(API_CLUSTERMGR, mask); NodeReceiverGroup rg(API_CLUSTERMGR, mask);
sendSignal(rg, api.gsn, signal, len, JBB); // forward sections sendSignal(rg, api.gsn, signal, len, JBB); // forward sections
} }
void
Qmgr::execSTOP_REQ(Signal* signal)
{
jamEntry();
c_stopReq = * (StopReq*)signal->getDataPtr();
if (c_stopReq.senderRef)
{
ndbrequire(NdbNodeBitmask::get(c_stopReq.nodes, getOwnNodeId()));
StopConf *conf = (StopConf*)signal->getDataPtrSend();
conf->senderData = c_stopReq.senderData;
conf->nodeState = getOwnNodeId();
sendSignal(c_stopReq.senderRef,
GSN_STOP_CONF, signal, StopConf::SignalLength, JBA);
}
}
bool
Qmgr::check_multi_node_shutdown(Signal* signal)
{
if (c_stopReq.senderRef &&
NdbNodeBitmask::get(c_stopReq.nodes, getOwnNodeId()))
{
jam();
if(StopReq::getPerformRestart(c_stopReq.requestInfo))
{
jam();
StartOrd * startOrd = (StartOrd *)&signal->theData[0];
startOrd->restartInfo = c_stopReq.requestInfo;
EXECUTE_DIRECT(CMVMI, GSN_START_ORD, signal, 2);
} else {
EXECUTE_DIRECT(CMVMI, GSN_STOP_ORD, signal, 1);
}
return true;
}
return false;
}
...@@ -55,6 +55,12 @@ enum ndbd_options { ...@@ -55,6 +55,12 @@ enum ndbd_options {
NDB_STD_OPTS_VARS; NDB_STD_OPTS_VARS;
// XXX should be my_bool ??? // XXX should be my_bool ???
static int _daemon, _no_daemon, _foreground, _initial, _no_start; static int _daemon, _no_daemon, _foreground, _initial, _no_start;
static int _initialstart;
static const char* _nowait_nodes;
extern Uint32 g_start_type;
extern NdbNodeBitmask g_nowait_nodes;
/** /**
* Arguments to NDB process * Arguments to NDB process
*/ */
...@@ -82,6 +88,14 @@ static struct my_option my_long_options[] = ...@@ -82,6 +88,14 @@ static struct my_option my_long_options[] =
" (implies --nodaemon)", " (implies --nodaemon)",
(gptr*) &_foreground, (gptr*) &_foreground, 0, (gptr*) &_foreground, (gptr*) &_foreground, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "nowait-nodes", NO_ARG,
"Nodes that will not be waited for during start",
(gptr*) &_nowait_nodes, (gptr*) &_nowait_nodes, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "initial-start", NO_ARG,
"Perform initial start",
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };
static void short_usage_sub(void) static void short_usage_sub(void)
...@@ -150,6 +164,37 @@ Configuration::init(int argc, char** argv) ...@@ -150,6 +164,37 @@ Configuration::init(int argc, char** argv)
globalData.ownId= 0; globalData.ownId= 0;
if (_nowait_nodes)
{
BaseString str(_nowait_nodes);
Vector<BaseString> arr;
str.split(arr, ",");
for (Uint32 i = 0; i<arr.size(); i++)
{
char *endptr = 0;
long val = strtol(arr[i].c_str(), &endptr, 10);
if (*endptr)
{
ndbout_c("Unable to parse nowait-nodes argument: %s : %s",
arr[i].c_str(), _nowait_nodes);
exit(-1);
}
if (! (val > 0 && val < MAX_NDB_NODES))
{
ndbout_c("Invalid nodeid specified in nowait-nodes: %d : %s",
val, _nowait_nodes);
exit(-1);
}
g_nowait_nodes.set(val);
}
}
if (_initialstart)
{
_initialStart = true;
g_start_type |= (1 << NodeState::ST_INITIAL_START);
}
return true; return true;
} }
......
...@@ -1109,9 +1109,14 @@ NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames) ...@@ -1109,9 +1109,14 @@ NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames)
// Copy name to m_buffer to get a word sized buffer // Copy name to m_buffer to get a word sized buffer
m_buffer.clear(); m_buffer.clear();
m_buffer.grow(namelen_words*4); m_buffer.grow(namelen_words*4+4);
m_buffer.append(name.c_str(), namelen); m_buffer.append(name.c_str(), namelen);
#ifndef IGNORE_VALGRIND_WARNINGS
Uint32 pad = 0;
m_buffer.append(&pad, 4);
#endif
LinearSectionPtr ptr[1]; LinearSectionPtr ptr[1];
ptr[0].p= (Uint32*)m_buffer.get_data(); ptr[0].p= (Uint32*)m_buffer.get_data();
ptr[0].sz= namelen_words; ptr[0].sz= namelen_words;
......
...@@ -427,19 +427,26 @@ NdbLinHash<C>::getNext(NdbElement_t<C> * curr){ ...@@ -427,19 +427,26 @@ NdbLinHash<C>::getNext(NdbElement_t<C> * curr){
return curr->next; return curr->next;
int dir = 0, seg = 0; int dir = 0, seg = 0;
int counts;
if(curr != 0){ if(curr != 0)
{
getBucket(curr->hash, &dir, &seg); getBucket(curr->hash, &dir, &seg);
counts = seg + 1;
}
else
{
counts = 0;
} }
for(int countd = dir; countd < DIRECTORYSIZE;countd++ ){ for(int countd = dir; countd < DIRECTORYSIZE;countd++ ){
if (directory[countd] != 0) { if (directory[countd] != 0) {
for(int counts = seg + 1; counts < SEGMENTSIZE; counts++ ){ for(; counts < SEGMENTSIZE; counts++ ){
if (directory[countd]->elements[counts] != 0) { if (directory[countd]->elements[counts] != 0) {
return directory[countd]->elements[counts]; return directory[countd]->elements[counts];
} }
} }
} }
counts = 0;
} }
return 0; return 0;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <NdbRestarts.hpp> #include <NdbRestarts.hpp>
#include <Vector.hpp> #include <Vector.hpp>
#include <signaldata/DumpStateOrd.hpp> #include <signaldata/DumpStateOrd.hpp>
#include <Bitmask.hpp>
int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
...@@ -669,6 +669,206 @@ err: ...@@ -669,6 +669,206 @@ err:
return NDBT_FAILED; return NDBT_FAILED;
} }
int
runBug18612(NDBT_Context* ctx, NDBT_Step* step){
// Assume two replicas
NdbRestarter restarter;
if (restarter.getNumDbNodes() < 2)
{
ctx->stopTest();
return NDBT_OK;
}
Uint32 cnt = restarter.getNumDbNodes();
for(int loop = 0; loop < ctx->getNumLoops(); loop++)
{
int partition0[256];
int partition1[256];
bzero(partition0, sizeof(partition0));
bzero(partition1, sizeof(partition1));
Bitmask<4> nodesmask;
Uint32 node1 = restarter.getDbNodeId(rand()%cnt);
for (Uint32 i = 0; i<cnt/2; i++)
{
do {
int tmp = restarter.getRandomNodeOtherNodeGroup(node1, rand());
if (tmp == -1)
break;
node1 = tmp;
} while(nodesmask.get(node1));
partition0[i] = node1;
partition1[i] = restarter.getRandomNodeSameNodeGroup(node1, rand());
ndbout_c("nodes %d %d", node1, partition1[i]);
assert(!nodesmask.get(node1));
assert(!nodesmask.get(partition1[i]));
nodesmask.set(node1);
nodesmask.set(partition1[i]);
}
ndbout_c("done");
int dump[255];
dump[0] = DumpStateOrd::NdbcntrStopNodes;
memcpy(dump + 1, partition0, sizeof(int)*cnt/2);
Uint32 master = restarter.getMasterNodeId();
if (restarter.dumpStateOneNode(master, dump, 1+cnt/2))
return NDBT_FAILED;
if (restarter.waitNodesNoStart(partition0, cnt/2))
return NDBT_FAILED;
int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
if (restarter.dumpStateAllNodes(val2, 2))
return NDBT_FAILED;
if (restarter.insertErrorInAllNodes(932))
return NDBT_FAILED;
dump[0] = 9000;
memcpy(dump + 1, partition0, sizeof(int)*cnt/2);
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateOneNode(partition1[i], dump, 1+cnt/2))
return NDBT_FAILED;
dump[0] = 9000;
memcpy(dump + 1, partition1, sizeof(int)*cnt/2);
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateOneNode(partition0[i], dump, 1+cnt/2))
return NDBT_FAILED;
if (restarter.startNodes(partition0, cnt/2))
return NDBT_FAILED;
if (restarter.waitNodesStartPhase(partition0, cnt/2, 2))
return NDBT_FAILED;
dump[0] = 9001;
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateAllNodes(dump, 2))
return NDBT_FAILED;
if (restarter.waitNodesNoStart(partition0, cnt/2))
return NDBT_FAILED;
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.restartOneDbNode(partition0[i], true, true, true))
return NDBT_FAILED;
if (restarter.waitNodesNoStart(partition0, cnt/2))
return NDBT_FAILED;
if (restarter.startAll())
return NDBT_FAILED;
if (restarter.waitClusterStarted())
return NDBT_FAILED;
}
return NDBT_OK;
}
int
runBug18612SR(NDBT_Context* ctx, NDBT_Step* step){
// Assume two replicas
NdbRestarter restarter;
if (restarter.getNumDbNodes() < 2)
{
ctx->stopTest();
return NDBT_OK;
}
Uint32 cnt = restarter.getNumDbNodes();
for(int loop = 0; loop < ctx->getNumLoops(); loop++)
{
int partition0[256];
int partition1[256];
bzero(partition0, sizeof(partition0));
bzero(partition1, sizeof(partition1));
Bitmask<4> nodesmask;
Uint32 node1 = restarter.getDbNodeId(rand()%cnt);
for (Uint32 i = 0; i<cnt/2; i++)
{
do {
int tmp = restarter.getRandomNodeOtherNodeGroup(node1, rand());
if (tmp == -1)
break;
node1 = tmp;
} while(nodesmask.get(node1));
partition0[i] = node1;
partition1[i] = restarter.getRandomNodeSameNodeGroup(node1, rand());
ndbout_c("nodes %d %d", node1, partition1[i]);
assert(!nodesmask.get(node1));
assert(!nodesmask.get(partition1[i]));
nodesmask.set(node1);
nodesmask.set(partition1[i]);
}
ndbout_c("done");
if (restarter.restartAll(false, true, false))
return NDBT_FAILED;
int dump[255];
dump[0] = 9000;
memcpy(dump + 1, partition0, sizeof(int)*cnt/2);
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateOneNode(partition1[i], dump, 1+cnt/2))
return NDBT_FAILED;
dump[0] = 9000;
memcpy(dump + 1, partition1, sizeof(int)*cnt/2);
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateOneNode(partition0[i], dump, 1+cnt/2))
return NDBT_FAILED;
int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
if (restarter.dumpStateAllNodes(val2, 2))
return NDBT_FAILED;
if (restarter.insertErrorInAllNodes(932))
return NDBT_FAILED;
if (restarter.startAll())
return NDBT_FAILED;
if (restarter.waitClusterStartPhase(2))
return NDBT_FAILED;
dump[0] = 9001;
for (Uint32 i = 0; i<cnt/2; i++)
if (restarter.dumpStateAllNodes(dump, 2))
return NDBT_FAILED;
if (restarter.waitClusterNoStart(30))
if (restarter.waitNodesNoStart(partition0, cnt/2, 10))
if (restarter.waitNodesNoStart(partition1, cnt/2, 10))
return NDBT_FAILED;
if (restarter.startAll())
return NDBT_FAILED;
if (restarter.waitClusterStarted())
return NDBT_FAILED;
}
return NDBT_OK;
}
NDBT_TESTSUITE(testNodeRestart); NDBT_TESTSUITE(testNodeRestart);
TESTCASE("NoLoad", TESTCASE("NoLoad",
"Test that one node at a time can be stopped and then restarted "\ "Test that one node at a time can be stopped and then restarted "\
...@@ -963,6 +1163,18 @@ TESTCASE("Bug18414", ...@@ -963,6 +1163,18 @@ TESTCASE("Bug18414",
STEP(runBug18414); STEP(runBug18414);
FINALIZER(runClearTable); FINALIZER(runClearTable);
} }
TESTCASE("Bug18612",
"Test bug with partitioned clusters"){
INITIALIZER(runLoadTable);
STEP(runBug18612);
FINALIZER(runClearTable);
}
TESTCASE("Bug18612SR",
"Test bug with partitioned clusters"){
INITIALIZER(runLoadTable);
STEP(runBug18612SR);
FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testNodeRestart); NDBT_TESTSUITE_END(testNodeRestart);
int main(int argc, const char** argv){ int main(int argc, const char** argv){
......
...@@ -433,10 +433,18 @@ args: -n Bug16772 T1 ...@@ -433,10 +433,18 @@ args: -n Bug16772 T1
#cmd: testSystemRestart #cmd: testSystemRestart
#args: -n Bug18385 T1 #args: -n Bug18385 T1
# #
max-time: 500 max-time: 1000
cmd: testNodeRestart cmd: testNodeRestart
args: -n Bug18414 T1 args: -n Bug18414 T1
max-time: 1000
cmd: testNodeRestart
args: -n Bug18612 T1
max-time: 1000
cmd: testNodeRestart
args: -n Bug18612SR T1
# OLD FLEX # OLD FLEX
max-time: 500 max-time: 500
cmd: flexBench cmd: flexBench
......
...@@ -445,8 +445,7 @@ int twoNodeFailure(NdbRestarter& _restarter, ...@@ -445,8 +445,7 @@ int twoNodeFailure(NdbRestarter& _restarter,
<< ") secs " << endl; << ") secs " << endl;
NdbSleep_SecSleep(seconds); NdbSleep_SecSleep(seconds);
randomId = (rand() % _restarter.getNumDbNodes()); nodeId = _restarter.getRandomNodeOtherNodeGroup(nodeId, rand());
nodeId = _restarter.getDbNodeId(randomId);
g_info << _restart->m_name << ": node = "<< nodeId << endl; g_info << _restart->m_name << ": node = "<< nodeId << endl;
CHECK(_restarter.insertErrorInNode(nodeId, 9999) == 0, CHECK(_restarter.insertErrorInNode(nodeId, 9999) == 0,
......
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