summaryrefslogtreecommitdiff
path: root/ndb
diff options
context:
space:
mode:
authorunknown <tomas@poseidon.mysql.com>2007-03-07 10:46:44 +0700
committerunknown <tomas@poseidon.mysql.com>2007-03-07 10:46:44 +0700
commit5d2ad21b624627868fa4861cfc601f56a4193fac (patch)
tree1418c38b36183a6816570c2aecdd73dd568c6a8e /ndb
parenta58b9b050a4ca36bc6c7617476811bb7f23fc7c7 (diff)
downloadmariadb-git-5d2ad21b624627868fa4861cfc601f56a4193fac.tar.gz
Bug#25275 SINGLE USER MODE prevents ALTER on non-ndb tables for other mysqld nodes
- refactor single user and move single user checks from api to kernel
Diffstat (limited to 'ndb')
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp11
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp133
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp2
-rw-r--r--ndb/src/ndbapi/Ndb.cpp11
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp16
5 files changed, 143 insertions, 30 deletions
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index d6c4529bb72..988aa091127 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -1835,9 +1835,14 @@ private:
Uint32 transid2);
void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket);
- bool getAllowStartTransaction() const {
- if(getNodeState().getSingleUserMode())
- return true;
+ bool getAllowStartTransaction(Uint32 nodeId) const {
+ if (unlikely(getNodeState().getSingleUserMode()))
+ {
+ if (getNodeState().getSingleUserApi() == nodeId)
+ return true;
+ else
+ return false;
+ }
return getNodeState().startLevel < NodeState::SL_STOPPING_2;
}
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 2b2e0e649a4..82c8e4a9634 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -1199,16 +1199,14 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
const NodeId senderNodeId = refToNode(tapiBlockref);
const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
- if(!(senderNodeId == getNodeState().getSingleUserApi()) &&
- !getNodeState().getSingleUserMode()) {
- if(!(sl==NodeState::SL_SINGLEUSER &&
- senderNodeId == getNodeState().getSingleUserApi())) {
+ {
+ {
if (!(sl == NodeState::SL_STARTED ||
(sl == NodeState::SL_STARTING && local == true))) {
jam();
- Uint32 errCode;
- if(!(sl == NodeState::SL_SINGLEUSER && local))
+ Uint32 errCode = 0;
+ if(!local)
{
switch(sl){
case NodeState::SL_STARTING:
@@ -1216,6 +1214,9 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
break;
case NodeState::SL_STOPPING_1:
case NodeState::SL_STOPPING_2:
+ if (getNodeState().getSingleUserMode() &&
+ getNodeState().getSingleUserApi() == senderNodeId)
+ break;
case NodeState::SL_STOPPING_3:
case NodeState::SL_STOPPING_4:
if(getNodeState().stopping.systemShutdown)
@@ -1224,16 +1225,21 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
break;
case NodeState::SL_SINGLEUSER:
+ if (getNodeState().getSingleUserApi() == senderNodeId)
+ break;
errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
break;
default:
errCode = ZWRONG_STATE;
break;
}
- signal->theData[0] = tapiPointer;
- signal->theData[1] = errCode;
- sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
- return;
+ if (errCode)
+ {
+ signal->theData[0] = tapiPointer;
+ signal->theData[1] = errCode;
+ sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
+ return;
+ }
}//if (!(sl == SL_SINGLEUSER))
} //if
}
@@ -1720,8 +1726,14 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
* Initialize object before starting error handling
*/
initApiConnectRec(signal, apiConnectptr.p, true);
+start_failure:
switch(getNodeState().startLevel){
case NodeState::SL_STOPPING_2:
+ if (getNodeState().getSingleUserMode())
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ break;
+ }
case NodeState::SL_STOPPING_3:
case NodeState::SL_STOPPING_4:
if(getNodeState().stopping.systemShutdown)
@@ -1732,6 +1744,12 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case NodeState::SL_SINGLEUSER:
terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
break;
+ case NodeState::SL_STOPPING_1:
+ if (getNodeState().getSingleUserMode())
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ break;
+ }
default:
terrorCode = ZWRONG_STATE;
break;
@@ -1753,6 +1771,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return;
}
+ case 60:
+ {
+ jam();
+ initApiConnectRec(signal, apiConnectptr.p, true);
+ apiConnectptr.p->m_exec_flag = 1;
+ goto start_failure;
+ }
default:
jam();
systemErrorLab(signal, __LINE__);
@@ -2481,6 +2506,7 @@ Dbtc::seizeCacheRecord(Signal* signal)
/*****************************************************************************/
void Dbtc::execTCKEYREQ(Signal* signal)
{
+ Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
UintR compare_transid1, compare_transid2;
UintR titcLenAiInTckeyreq;
UintR TkeyLength;
@@ -2526,7 +2552,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regApiPtr->m_exec_flag |= TexecFlag;
switch (regApiPtr->apiConnectstate) {
case CS_CONNECTED:{
- if (TstartFlag == 1 && getAllowStartTransaction() == true){
+ if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId) == true){
//---------------------------------------------------------------------
// Initialise API connect record if transaction is started.
//---------------------------------------------------------------------
@@ -2534,7 +2560,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
initApiConnectRec(signal, regApiPtr);
regApiPtr->m_exec_flag = TexecFlag;
} else {
- if(getAllowStartTransaction() == true){
+ if(getAllowStartTransaction(sendersNodeId) == true){
/*------------------------------------------------------------------
* WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
* RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
@@ -2544,9 +2570,9 @@ void Dbtc::execTCKEYREQ(Signal* signal)
return;
} else {
/**
- * getAllowStartTransaction() == false
+ * getAllowStartTransaction(sendersNodeId) == false
*/
- TCKEY_abort(signal, 57);
+ TCKEY_abort(signal, TexecFlag ? 60 : 57);
return;
}//if
}
@@ -6161,9 +6187,11 @@ and otherwise we spread it out 310 ms.
void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
{
Uint32 end_ptr, time_passed, time_out_value, mask_value;
+ Uint32 old_mask_value= 0;
const Uint32 api_con_sz= capiConnectFilesize;
const Uint32 tc_timer= ctcTimer;
const Uint32 time_out_param= ctimeOutValue;
+ const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
ctimeOutCheckHeartbeat = tc_timer;
@@ -6184,11 +6212,39 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
jam();
mask_value= 31;
}
+ if (time_out_param != old_time_out_param &&
+ getNodeState().getSingleUserMode())
+ {
+ // abort during single user mode, use old_mask_value as flag
+ // and calculate value to be used for connections with allowed api
+ if (old_time_out_param > 300) {
+ jam();
+ old_mask_value= 63;
+ } else if (old_time_out_param < 30) {
+ jam();
+ old_mask_value= 7;
+ } else {
+ jam();
+ old_mask_value= 31;
+ }
+ }
for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
Uint32 api_timer= getApiConTimer(api_con_ptr);
jam();
if (api_timer != 0) {
time_out_value= time_out_param + (api_con_ptr & mask_value);
+ if (unlikely(old_mask_value)) // abort during single user mode
+ {
+ apiConnectptr.i = api_con_ptr;
+ ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ if (getNodeState().getSingleUserApi() ==
+ refToNode(apiConnectptr.p->ndbapiBlockref))
+ {
+ // api allowed during single user, use original timeout
+ time_out_value=
+ old_time_out_param + (api_con_ptr & old_mask_value);
+ }
+ }
time_passed= tc_timer - api_timer;
if (time_passed > time_out_value)
{
@@ -6805,6 +6861,33 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
c_scan_frag_pool.getPtr(ptr, TscanConPtr);
DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
+ const Uint32 time_out_param= ctimeOutValue;
+ const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
+
+ if (unlikely(time_out_param != old_time_out_param &&
+ getNodeState().getSingleUserMode()))
+ {
+ jam();
+ ScanRecordPtr scanptr;
+ scanptr.i = ptr.p->scanRec;
+ ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+ ApiConnectRecordPtr TlocalApiConnectptr;
+ TlocalApiConnectptr.i = scanptr.p->scanApiRec;
+ ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
+
+ if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
+ getNodeState().getSingleUserApi())
+ {
+ jam();
+ Uint32 val = ctcTimer - ptr.p->scanFragTimer;
+ if (val <= old_time_out_param)
+ {
+ jam();
+ goto next;
+ }
+ }
+ }
+
/*-------------------------------------------------------------------------*/
// The scan fragment has expired its timeout. Check its state to decide
// what to do.
@@ -6866,6 +6949,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
break;
}//switch
+next:
signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
signal->theData[1] = TscanConPtr + 1;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
@@ -8696,6 +8780,14 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
}
}
+ if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
+ getNodeState().getSingleUserApi() !=
+ refToNode(apiConnectptr.p->ndbapiBlockref))
+ {
+ errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ goto SCAN_TAB_error;
+ }
+
seizeTcConnect(signal);
tcConnectptr.p->apiConnect = apiConnectptr.i;
tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
@@ -11038,7 +11130,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal)
const Uint32 senderData = req->senderData;
const BlockReference senderRef = req->senderRef;
- if(getAllowStartTransaction() == true && !getNodeState().getSingleUserMode()){
+ if(getAllowStartTransaction(refToNode(senderRef)) == true && !getNodeState().getSingleUserMode()){
jam();
ref->senderData = senderData;
@@ -11466,6 +11558,17 @@ void Dbtc::execTCINDXREQ(Signal* signal)
regApiPtr->transid[1] = tcIndxReq->transId2;
}//if
+ if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
+ getNodeState().getSingleUserApi() !=
+ refToNode(regApiPtr->ndbapiBlockref))
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
+ apiConnectptr = transPtr;
+ abortErrorLab(signal);
+ return;
+ }
+
if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
jam();
// Failed to allocate index operation
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index 060e5f71b6c..7ab3ee07197 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -405,7 +405,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
node.m_state = apiRegConf->nodeState;
if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED ||
- node.m_state.startLevel == NodeState::SL_SINGLEUSER)){
+ node.m_state.getSingleUserMode())){
set_node_alive(node, true);
} else {
set_node_alive(node, false);
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index 80bf0315b9c..8a1ccd53558 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -56,6 +56,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tConNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive = 1;
}//if
@@ -79,6 +81,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
@@ -107,6 +111,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
@@ -207,6 +213,11 @@ Ndb::NDB_connect(Uint32 tNode)
DBUG_PRINT("info",
("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d",
tReturnCode, tNdbCon->Status()));
+ if (theError.code == 299)
+ {
+ // single user mode so no need to retry with other node
+ DBUG_RETURN(-1);
+ }
DBUG_RETURN(3);
}//if
}//Ndb::NDB_connect()
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index 2e0f08601e5..5a826bc2309 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -315,7 +315,8 @@ inline
bool
TransporterFacade::get_node_stopping(NodeId n) const {
const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
- return ((node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
+ return (!node.m_state.getSingleUserMode() &&
+ (node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
(node.m_state.startLevel == NodeState::SL_STOPPING_2));
}
@@ -326,16 +327,9 @@ TransporterFacade::getIsNodeSendable(NodeId n) const {
const Uint32 startLevel = node.m_state.startLevel;
if (node.m_info.m_type == NodeInfo::DB) {
- if(node.m_state.singleUserMode &&
- ownId() == node.m_state.singleUserApi) {
- return (node.compatible &&
- (node.m_state.startLevel == NodeState::SL_STOPPING_1 ||
- node.m_state.startLevel == NodeState::SL_STARTED ||
- node.m_state.startLevel == NodeState::SL_SINGLEUSER));
- }
- else
- return node.compatible && (startLevel == NodeState::SL_STARTED ||
- startLevel == NodeState::SL_STOPPING_1);
+ return node.compatible && (startLevel == NodeState::SL_STARTED ||
+ startLevel == NodeState::SL_STOPPING_1 ||
+ node.m_state.getSingleUserMode());
} else if (node.m_info.m_type == NodeInfo::REP) {
/**
* @todo Check that REP node actually has received API_REG_REQ