Commit a80c9cce authored by unknown's avatar unknown

Bug #25275 SINGLE USER MODE prevents ALTER on non-ndb tables for other mysqld nodes


ndb/include/kernel/signaldata/DictTabInfo.hpp:
  add single user mode field in table definition
ndb/include/ndb_constants.h:
  new constants for single usermode option of tables
ndb/include/ndbapi/NdbDictionary.hpp:
  add single user mode field in table definition
ndb/src/common/debugger/signaldata/DictTabInfo.cpp:
  add single user mode field in table definition
ndb/src/kernel/blocks/dbdict/Dbdict.cpp:
  add single user mode field in table definition
  send this infor to TC
ndb/src/kernel/blocks/dbdict/Dbdict.hpp:
  add single user mode field in table definition
ndb/src/kernel/blocks/dbtc/Dbtc.hpp:
  single user table mode on table object
  merge some flags from uint8 to bits
  get allow transaction to also check single user mode
ndb/src/kernel/blocks/dbtc/DbtcMain.cpp:
  single user table mode on table object
  merge some flags from uint8 to bits
  get allow transaction to also check single user mode
ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp:
  set single user mode flag on system tables to make them always updatable
ndb/src/ndbapi/NdbDictionary.cpp:
  get/set functions for single user mode on tables
ndb/src/ndbapi/NdbDictionaryImpl.cpp:
  get/set functions for single user mode on tables
ndb/src/ndbapi/NdbDictionaryImpl.hpp:
  get/set functions for single user mode on tables
ndb/test/src/NDBT_Table.cpp:
  print single user mode
parent 5d2ad21b
...@@ -126,6 +126,8 @@ public: ...@@ -126,6 +126,8 @@ public:
MinRowsLow = 143, MinRowsLow = 143,
MinRowsHigh = 144, MinRowsHigh = 144,
SingleUserMode = 152,
TableEnd = 999, TableEnd = 999,
AttributeName = 1000, // String, Mandatory AttributeName = 1000, // String, Mandatory
...@@ -273,7 +275,8 @@ public: ...@@ -273,7 +275,8 @@ public:
Uint32 MaxRowsHigh; Uint32 MaxRowsHigh;
Uint32 MinRowsLow; Uint32 MinRowsLow;
Uint32 MinRowsHigh; Uint32 MinRowsHigh;
Uint32 SingleUserMode;
void init(); void init();
}; };
......
...@@ -68,4 +68,11 @@ ...@@ -68,4 +68,11 @@
#define NDB_TYPE_MAX 31 #define NDB_TYPE_MAX 31
/*
* Table single user mode
*/
#define NDB_SUM_LOCKED 0
#define NDB_SUM_READONLY 1
#define NDB_SUM_READ_WRITE 2
#endif #endif
...@@ -497,6 +497,15 @@ public: ...@@ -497,6 +497,15 @@ public:
*/ */
class Table : public Object { class Table : public Object {
public: public:
/*
* Single user mode specifies access rights to table during single user mode
*/
enum SingleUserMode {
SingleUserModeLocked = NDB_SUM_LOCKED,
SingleUserModeReadOnly = NDB_SUM_READONLY,
SingleUserModeReadWrite = NDB_SUM_READ_WRITE
};
/** /**
* @name General * @name General
* @{ * @{
...@@ -735,6 +744,13 @@ public: ...@@ -735,6 +744,13 @@ public:
void setMinRows(Uint64 minRows); void setMinRows(Uint64 minRows);
Uint64 getMinRows() const; Uint64 getMinRows() const;
/**
* Set/Get SingleUserMode
*/
void setSingleUserMode(enum SingleUserMode);
enum SingleUserMode getSingleUserMode() const;
/** @} *******************************************************************/ /** @} *******************************************************************/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
......
...@@ -51,6 +51,7 @@ DictTabInfo::TableMapping[] = { ...@@ -51,6 +51,7 @@ DictTabInfo::TableMapping[] = {
DTIMAP(Table, MaxRowsHigh, MaxRowsHigh), DTIMAP(Table, MaxRowsHigh, MaxRowsHigh),
DTIMAP(Table, MinRowsLow, MinRowsLow), DTIMAP(Table, MinRowsLow, MinRowsLow),
DTIMAP(Table, MinRowsHigh, MinRowsHigh), DTIMAP(Table, MinRowsHigh, MinRowsHigh),
DTIMAP(Table, SingleUserMode, SingleUserMode),
DTIBREAK(AttributeName) DTIBREAK(AttributeName)
}; };
...@@ -131,6 +132,8 @@ DictTabInfo::Table::init(){ ...@@ -131,6 +132,8 @@ DictTabInfo::Table::init(){
MaxRowsHigh = 0; MaxRowsHigh = 0;
MinRowsLow = 0; MinRowsLow = 0;
MinRowsHigh = 0; MinRowsHigh = 0;
SingleUserMode = 0;
} }
void void
......
...@@ -289,7 +289,7 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w, ...@@ -289,7 +289,7 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh); w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow); w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh); w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
if(!signal) if(!signal)
{ {
w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount); w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
...@@ -1500,6 +1500,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr) ...@@ -1500,6 +1500,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->maxRowsHigh = 0; tablePtr.p->maxRowsHigh = 0;
tablePtr.p->minRowsLow = 0; tablePtr.p->minRowsLow = 0;
tablePtr.p->minRowsHigh = 0; tablePtr.p->minRowsHigh = 0;
tablePtr.p->singleUserMode = 0;
tablePtr.p->storedTable = true; tablePtr.p->storedTable = true;
tablePtr.p->tableType = DictTabInfo::UserTable; tablePtr.p->tableType = DictTabInfo::UserTable;
tablePtr.p->primaryTableId = RNIL; tablePtr.p->primaryTableId = RNIL;
...@@ -4718,8 +4719,9 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){ ...@@ -4718,8 +4719,9 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[4] = (Uint32)tabPtr.p->tableType; signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key; signal->theData[5] = createTabPtr.p->key;
signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey; signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
signal->theData[7] = (Uint32)tabPtr.p->singleUserMode;
sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 8, JBB);
return; return;
} }
...@@ -5084,6 +5086,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it, ...@@ -5084,6 +5086,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->maxRowsHigh = tableDesc.MaxRowsHigh; tablePtr.p->maxRowsHigh = tableDesc.MaxRowsHigh;
tablePtr.p->minRowsLow = tableDesc.MinRowsLow; tablePtr.p->minRowsLow = tableDesc.MinRowsLow;
tablePtr.p->minRowsHigh = tableDesc.MinRowsHigh; tablePtr.p->minRowsHigh = tableDesc.MinRowsHigh;
tablePtr.p->singleUserMode = tableDesc.SingleUserMode;
Uint64 maxRows = Uint64 maxRows =
(((Uint64)tablePtr.p->maxRowsHigh) << 32) + tablePtr.p->maxRowsLow; (((Uint64)tablePtr.p->maxRowsHigh) << 32) + tablePtr.p->maxRowsLow;
......
...@@ -237,6 +237,11 @@ public: ...@@ -237,6 +237,11 @@ public:
char frmData[MAX_FRM_DATA_SIZE]; char frmData[MAX_FRM_DATA_SIZE];
Uint32 fragmentCount; Uint32 fragmentCount;
/*
* Access rights to table during single user mode
*/
Uint8 singleUserMode;
}; };
typedef Ptr<TableRecord> TableRecordPtr; typedef Ptr<TableRecord> TableRecordPtr;
......
...@@ -702,6 +702,7 @@ public: ...@@ -702,6 +702,7 @@ public:
Uint8 tckeyrec; // ndrad frn R Uint8 tckeyrec; // ndrad frn R
Uint8 tcindxrec; Uint8 tcindxrec;
Uint8 apiFailState; // ndrad frn R Uint8 apiFailState; // ndrad frn R
Uint8 singleUserMode;
ReturnSignal returnsignal; ReturnSignal returnsignal;
Uint8 timeOutCounter; Uint8 timeOutCounter;
...@@ -957,17 +958,28 @@ public: ...@@ -957,17 +958,28 @@ public:
/********************************************************/ /********************************************************/
struct TableRecord { struct TableRecord {
Uint32 currentSchemaVersion; Uint32 currentSchemaVersion;
Uint8 enabled; Uint16 m_flags;
Uint8 dropping;
Uint8 tableType; Uint8 tableType;
Uint8 storedTable; Uint8 singleUserMode;
enum {
TR_ENABLED = 1 << 0,
TR_DROPPING = 1 << 1,
TR_STORED_TABLE = 1 << 2
};
Uint8 get_enabled() const { return (m_flags & TR_ENABLED) != 0; }
Uint8 get_dropping() const { return (m_flags & TR_DROPPING) != 0; }
Uint8 get_storedTable() const { return (m_flags & TR_STORED_TABLE) != 0; }
void set_enabled(Uint8 f) { f ? m_flags |= (Uint16)TR_ENABLED : m_flags &= ~(Uint16)TR_ENABLED; }
void set_dropping(Uint8 f) { f ? m_flags |= (Uint16)TR_DROPPING : m_flags &= ~(Uint16)TR_DROPPING; }
void set_storedTable(Uint8 f) { f ? m_flags |= (Uint16)TR_STORED_TABLE : m_flags &= ~(Uint16)TR_STORED_TABLE; }
Uint8 noOfKeyAttr; Uint8 noOfKeyAttr;
Uint8 hasCharAttr; Uint8 hasCharAttr;
Uint8 noOfDistrKeys; Uint8 noOfDistrKeys;
bool checkTable(Uint32 schemaVersion) const { bool checkTable(Uint32 schemaVersion) const {
return enabled && !dropping && return get_enabled() && !get_dropping() &&
(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion)); (table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
} }
...@@ -1835,10 +1847,10 @@ private: ...@@ -1835,10 +1847,10 @@ private:
Uint32 transid2); Uint32 transid2);
void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket); void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket);
bool getAllowStartTransaction(Uint32 nodeId) const { bool getAllowStartTransaction(Uint32 nodeId, Uint32 table_single_user_mode) const {
if (unlikely(getNodeState().getSingleUserMode())) if (unlikely(getNodeState().getSingleUserMode()))
{ {
if (getNodeState().getSingleUserApi() == nodeId) if (getNodeState().getSingleUserApi() == nodeId || table_single_user_mode)
return true; return true;
else else
return false; return false;
......
...@@ -327,19 +327,21 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal) ...@@ -327,19 +327,21 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal)
tabptr.i = signal->theData[0]; tabptr.i = signal->theData[0];
ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord); ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
tabptr.p->currentSchemaVersion = signal->theData[1]; tabptr.p->currentSchemaVersion = signal->theData[1];
tabptr.p->storedTable = (bool)signal->theData[2]; tabptr.p->m_flags = 0;
tabptr.p->set_storedTable((bool)signal->theData[2]);
BlockReference retRef = signal->theData[3]; BlockReference retRef = signal->theData[3];
tabptr.p->tableType = (Uint8)signal->theData[4]; tabptr.p->tableType = (Uint8)signal->theData[4];
BlockReference retPtr = signal->theData[5]; BlockReference retPtr = signal->theData[5];
Uint32 noOfKeyAttr = signal->theData[6]; Uint32 noOfKeyAttr = signal->theData[6];
tabptr.p->singleUserMode = (Uint8)signal->theData[7];
ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX); ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i); const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
ndbrequire(noOfKeyAttr == desc->noOfKeyAttr); ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
ndbrequire(tabptr.p->enabled == false); ndbrequire(tabptr.p->get_enabled() == false);
tabptr.p->enabled = true; tabptr.p->set_enabled(true);
tabptr.p->dropping = false; tabptr.p->set_dropping(false);
tabptr.p->noOfKeyAttr = desc->noOfKeyAttr; tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
tabptr.p->hasCharAttr = desc->hasCharAttr; tabptr.p->hasCharAttr = desc->hasCharAttr;
tabptr.p->noOfDistrKeys = desc->noOfDistrKeys; tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
...@@ -363,7 +365,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal) ...@@ -363,7 +365,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
Uint32 senderRef = req->senderRef; Uint32 senderRef = req->senderRef;
Uint32 senderData = req->senderData; Uint32 senderData = req->senderData;
if(!tabPtr.p->enabled){ if(!tabPtr.p->get_enabled()){
jam(); jam();
PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend(); PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference(); ref->senderRef = reference();
...@@ -375,7 +377,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal) ...@@ -375,7 +377,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
return; return;
} }
if(tabPtr.p->dropping){ if(tabPtr.p->get_dropping()){
jam(); jam();
PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend(); PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference(); ref->senderRef = reference();
...@@ -387,7 +389,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal) ...@@ -387,7 +389,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
return; return;
} }
tabPtr.p->dropping = true; tabPtr.p->set_dropping(true);
tabPtr.p->dropTable.senderRef = senderRef; tabPtr.p->dropTable.senderRef = senderRef;
tabPtr.p->dropTable.senderData = senderData; tabPtr.p->dropTable.senderData = senderData;
...@@ -423,7 +425,7 @@ Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal) ...@@ -423,7 +425,7 @@ Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
tabPtr.i = conf->tableId; tabPtr.i = conf->tableId;
ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord); ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
ndbrequire(tabPtr.p->dropping == true); ndbrequire(tabPtr.p->get_dropping() == true);
Uint32 nodeId = refToNode(conf->senderRef); Uint32 nodeId = refToNode(conf->senderRef);
tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId); tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
...@@ -453,7 +455,7 @@ Dbtc::execWAIT_DROP_TAB_REF(Signal* signal) ...@@ -453,7 +455,7 @@ Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
tabPtr.i = ref->tableId; tabPtr.i = ref->tableId;
ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord); ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
ndbrequire(tabPtr.p->dropping == true); ndbrequire(tabPtr.p->get_dropping() == true);
Uint32 nodeId = refToNode(ref->senderRef); Uint32 nodeId = refToNode(ref->senderRef);
tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId); tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
...@@ -490,7 +492,7 @@ Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId) ...@@ -490,7 +492,7 @@ Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){ for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
jam(); jam();
ptrAss(tabPtr, tableRecord); ptrAss(tabPtr, tableRecord);
if(tabPtr.p->enabled && tabPtr.p->dropping){ if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){ if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
jam(); jam();
conf->senderRef = calcLqhBlockRef(nodeId); conf->senderRef = calcLqhBlockRef(nodeId);
...@@ -531,7 +533,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal) ...@@ -531,7 +533,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
Uint32 senderData = req->senderData; Uint32 senderData = req->senderData;
DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType; DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
if(!tabPtr.p->enabled && rt == DropTabReq::OnlineDropTab){ if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
jam(); jam();
DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend(); DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference(); ref->senderRef = reference();
...@@ -543,7 +545,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal) ...@@ -543,7 +545,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
return; return;
} }
if(!tabPtr.p->dropping && rt == DropTabReq::OnlineDropTab){ if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
jam(); jam();
DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend(); DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference(); ref->senderRef = reference();
...@@ -555,8 +557,8 @@ Dbtc::execDROP_TAB_REQ(Signal* signal) ...@@ -555,8 +557,8 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
return; return;
} }
tabPtr.p->enabled = false; tabPtr.p->set_enabled(false);
tabPtr.p->dropping = false; tabPtr.p->set_dropping(false);
DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend(); DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
conf->tableId = tabPtr.i; conf->tableId = tabPtr.i;
...@@ -1214,8 +1216,7 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) ...@@ -1214,8 +1216,7 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
break; break;
case NodeState::SL_STOPPING_1: case NodeState::SL_STOPPING_1:
case NodeState::SL_STOPPING_2: case NodeState::SL_STOPPING_2:
if (getNodeState().getSingleUserMode() && if (getNodeState().getSingleUserMode())
getNodeState().getSingleUserApi() == senderNodeId)
break; break;
case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_3:
case NodeState::SL_STOPPING_4: case NodeState::SL_STOPPING_4:
...@@ -1225,9 +1226,6 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) ...@@ -1225,9 +1226,6 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
errCode = ZNODE_SHUTDOWN_IN_PROGRESS; errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
break; break;
case NodeState::SL_SINGLEUSER: case NodeState::SL_SINGLEUSER:
if (getNodeState().getSingleUserApi() == senderNodeId)
break;
errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
break; break;
default: default:
errCode = ZWRONG_STATE; errCode = ZWRONG_STATE;
...@@ -2397,6 +2395,7 @@ void Dbtc::initApiConnectRec(Signal* signal, ...@@ -2397,6 +2395,7 @@ void Dbtc::initApiConnectRec(Signal* signal,
regApiPtr->buddyPtr = RNIL; regApiPtr->buddyPtr = RNIL;
regApiPtr->currSavePointId = 0; regApiPtr->currSavePointId = 0;
regApiPtr->m_transaction_nodes.clear(); regApiPtr->m_transaction_nodes.clear();
regApiPtr->singleUserMode = 0;
// Trigger data // Trigger data
releaseFiredTriggerData(&regApiPtr->theFiredTriggers), releaseFiredTriggerData(&regApiPtr->theFiredTriggers),
// Index data // Index data
...@@ -2550,9 +2549,12 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2550,9 +2549,12 @@ void Dbtc::execTCKEYREQ(Signal* signal)
bool isIndexOpReturn = regApiPtr->indexOpReturn; bool isIndexOpReturn = regApiPtr->indexOpReturn;
regApiPtr->isIndexOp = false; // Reset marker regApiPtr->isIndexOp = false; // Reset marker
regApiPtr->m_exec_flag |= TexecFlag; regApiPtr->m_exec_flag |= TexecFlag;
TableRecordPtr localTabptr;
localTabptr.i = TtabIndex;
localTabptr.p = &tableRecord[TtabIndex];
switch (regApiPtr->apiConnectstate) { switch (regApiPtr->apiConnectstate) {
case CS_CONNECTED:{ case CS_CONNECTED:{
if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId) == true){ if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Initialise API connect record if transaction is started. // Initialise API connect record if transaction is started.
//--------------------------------------------------------------------- //---------------------------------------------------------------------
...@@ -2560,7 +2562,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2560,7 +2562,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
initApiConnectRec(signal, regApiPtr); initApiConnectRec(signal, regApiPtr);
regApiPtr->m_exec_flag = TexecFlag; regApiPtr->m_exec_flag = TexecFlag;
} else { } else {
if(getAllowStartTransaction(sendersNodeId) == true){ if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
/*------------------------------------------------------------------ /*------------------------------------------------------------------
* WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
* RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
...@@ -2587,6 +2589,13 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2587,6 +2589,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
* the state will be CS_STARTED * the state will be CS_STARTED
*/ */
jam(); jam();
if (unlikely(getNodeState().getSingleUserMode()) &&
getNodeState().getSingleUserApi() != sendersNodeId &&
!localTabptr.p->singleUserMode)
{
TCKEY_abort(signal, TexecFlag ? 60 : 57);
return;
}
initApiConnectRec(signal, regApiPtr); initApiConnectRec(signal, regApiPtr);
regApiPtr->m_exec_flag = TexecFlag; regApiPtr->m_exec_flag = TexecFlag;
} else { } else {
...@@ -2607,6 +2616,10 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2607,6 +2616,10 @@ void Dbtc::execTCKEYREQ(Signal* signal)
case CS_ABORTING: case CS_ABORTING:
if (regApiPtr->abortState == AS_IDLE) { if (regApiPtr->abortState == AS_IDLE) {
if (TstartFlag == 1) { if (TstartFlag == 1) {
if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
TCKEY_abort(signal, TexecFlag ? 60 : 57);
return;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Previous transaction had been aborted and the abort was completed. // Previous transaction had been aborted and the abort was completed.
// It is then OK to start a new transaction again. // It is then OK to start a new transaction again.
...@@ -2670,9 +2683,6 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2670,9 +2683,6 @@ void Dbtc::execTCKEYREQ(Signal* signal)
return; return;
}//switch }//switch
TableRecordPtr localTabptr;
localTabptr.i = TtabIndex;
localTabptr.p = &tableRecord[TtabIndex];
if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) { if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
; ;
} else { } else {
...@@ -2731,6 +2741,8 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2731,6 +2741,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regTcPtr->savePointId = regApiPtr->currSavePointId; regTcPtr->savePointId = regApiPtr->currSavePointId;
regApiPtr->executingIndexOp = RNIL; regApiPtr->executingIndexOp = RNIL;
regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
if (TcKeyReq::getExecutingTrigger(Treqinfo)) { if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
// Save the TcOperationPtr for fireing operation // Save the TcOperationPtr for fireing operation
regTcPtr->triggeringOperation = TsenderData; regTcPtr->triggeringOperation = TsenderData;
...@@ -2862,7 +2874,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2862,7 +2874,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
* THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND * THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
* TEMP TABLES DON'T PARTICIPATE. * TEMP TABLES DON'T PARTICIPATE.
* -------------------------------------------------------------------- */ * -------------------------------------------------------------------- */
if (localTabptr.p->storedTable) { if (localTabptr.p->get_storedTable()) {
coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17; coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
} }
c_counters.cwriteCount = TwriteCount + 1; c_counters.cwriteCount = TwriteCount + 1;
...@@ -4721,6 +4733,7 @@ void Dbtc::copyApi(Signal* signal) ...@@ -4721,6 +4733,7 @@ void Dbtc::copyApi(Signal* signal)
regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec; regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
regApiPtr->commitAckMarker = TcommitAckMarker; regApiPtr->commitAckMarker = TcommitAckMarker;
regApiPtr->m_transaction_nodes = Tnodes; regApiPtr->m_transaction_nodes = Tnodes;
regApiPtr->singleUserMode = 0;
gcpPtr.i = TgcpPointer; gcpPtr.i = TgcpPointer;
ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord); ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
...@@ -4732,6 +4745,7 @@ void Dbtc::copyApi(Signal* signal) ...@@ -4732,6 +4745,7 @@ void Dbtc::copyApi(Signal* signal)
regTmpApiPtr->firstTcConnect = RNIL; regTmpApiPtr->firstTcConnect = RNIL;
regTmpApiPtr->lastTcConnect = RNIL; regTmpApiPtr->lastTcConnect = RNIL;
regTmpApiPtr->m_transaction_nodes.clear(); regTmpApiPtr->m_transaction_nodes.clear();
regTmpApiPtr->singleUserMode = 0;
releaseAllSeizedIndexOperations(regTmpApiPtr); releaseAllSeizedIndexOperations(regTmpApiPtr);
}//Dbtc::copyApi() }//Dbtc::copyApi()
...@@ -6237,8 +6251,9 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) ...@@ -6237,8 +6251,9 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
{ {
apiConnectptr.i = api_con_ptr; apiConnectptr.i = api_con_ptr;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
if (getNodeState().getSingleUserApi() == if ((getNodeState().getSingleUserApi() ==
refToNode(apiConnectptr.p->ndbapiBlockref)) refToNode(apiConnectptr.p->ndbapiBlockref)) ||
!(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
{ {
// api allowed during single user, use original timeout // api allowed during single user, use original timeout
time_out_value= time_out_value=
...@@ -8181,6 +8196,7 @@ void Dbtc::initApiConnectFail(Signal* signal) ...@@ -8181,6 +8196,7 @@ void Dbtc::initApiConnectFail(Signal* signal)
apiConnectptr.p->ndbapiConnect = 0; apiConnectptr.p->ndbapiConnect = 0;
apiConnectptr.p->buddyPtr = RNIL; apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->m_transaction_nodes.clear(); apiConnectptr.p->m_transaction_nodes.clear();
apiConnectptr.p->singleUserMode = 0;
setApiConTimer(apiConnectptr.i, 0, __LINE__); setApiConTimer(apiConnectptr.i, 0, __LINE__);
switch(ttransStatus){ switch(ttransStatus){
case LqhTransConf::Committed: case LqhTransConf::Committed:
...@@ -10076,6 +10092,7 @@ void Dbtc::initApiConnect(Signal* signal) ...@@ -10076,6 +10092,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL; apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0; apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear(); apiConnectptr.p->m_transaction_nodes.clear();
apiConnectptr.p->singleUserMode = 0;
}//for }//for
apiConnectptr.i = tiacTmp - 1; apiConnectptr.i = tiacTmp - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
...@@ -10104,6 +10121,7 @@ void Dbtc::initApiConnect(Signal* signal) ...@@ -10104,6 +10121,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL; apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0; apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear(); apiConnectptr.p->m_transaction_nodes.clear();
apiConnectptr.p->singleUserMode = 0;
}//for }//for
apiConnectptr.i = (2 * tiacTmp) - 1; apiConnectptr.i = (2 * tiacTmp) - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
...@@ -10132,6 +10150,7 @@ void Dbtc::initApiConnect(Signal* signal) ...@@ -10132,6 +10150,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL; apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0; apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear(); apiConnectptr.p->m_transaction_nodes.clear();
apiConnectptr.p->singleUserMode = 0;
}//for }//for
apiConnectptr.i = (3 * tiacTmp) - 1; apiConnectptr.i = (3 * tiacTmp) - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
...@@ -10316,10 +10335,11 @@ void Dbtc::initTable(Signal* signal) ...@@ -10316,10 +10335,11 @@ void Dbtc::initTable(Signal* signal)
refresh_watch_dog(); refresh_watch_dog();
ptrAss(tabptr, tableRecord); ptrAss(tabptr, tableRecord);
tabptr.p->currentSchemaVersion = 0; tabptr.p->currentSchemaVersion = 0;
tabptr.p->storedTable = true; tabptr.p->m_flags = 0;
tabptr.p->set_storedTable(true);
tabptr.p->tableType = 0; tabptr.p->tableType = 0;
tabptr.p->enabled = false; tabptr.p->set_enabled(false);
tabptr.p->dropping = false; tabptr.p->set_dropping(false);
tabptr.p->noOfKeyAttr = 0; tabptr.p->noOfKeyAttr = 0;
tabptr.p->hasCharAttr = 0; tabptr.p->hasCharAttr = 0;
tabptr.p->noOfDistrKeys = 0; tabptr.p->noOfDistrKeys = 0;
...@@ -10452,6 +10472,7 @@ void Dbtc::releaseAbortResources(Signal* signal) ...@@ -10452,6 +10472,7 @@ void Dbtc::releaseAbortResources(Signal* signal)
apiConnectptr.p->firstTcConnect = RNIL; apiConnectptr.p->firstTcConnect = RNIL;
apiConnectptr.p->lastTcConnect = RNIL; apiConnectptr.p->lastTcConnect = RNIL;
apiConnectptr.p->m_transaction_nodes.clear(); apiConnectptr.p->m_transaction_nodes.clear();
apiConnectptr.p->singleUserMode = 0;
// MASV let state be CS_ABORTING until all // MASV let state be CS_ABORTING until all
// signals in the "air" have been received. Reset to CS_CONNECTED // signals in the "air" have been received. Reset to CS_CONNECTED
...@@ -11130,7 +11151,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal) ...@@ -11130,7 +11151,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal)
const Uint32 senderData = req->senderData; const Uint32 senderData = req->senderData;
const BlockReference senderRef = req->senderRef; const BlockReference senderRef = req->senderRef;
if(getAllowStartTransaction(refToNode(senderRef)) == true && !getNodeState().getSingleUserMode()){ if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
jam(); jam();
ref->senderData = senderData; ref->senderData = senderData;
...@@ -13366,9 +13387,9 @@ void Dbtc::deleteFromIndexTable(Signal* signal, ...@@ -13366,9 +13387,9 @@ void Dbtc::deleteFromIndexTable(Signal* signal,
Uint32 Uint32
Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const { Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
if(!enabled) if(!get_enabled())
return ZNO_SUCH_TABLE; return ZNO_SUCH_TABLE;
if(dropping) if(get_dropping())
return ZDROP_TABLE_IN_PROGRESS; return ZDROP_TABLE_IN_PROGRESS;
if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion)) if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
return ZWRONG_SCHEMA_VERSION_ERROR; return ZWRONG_SCHEMA_VERSION_ERROR;
......
...@@ -1645,6 +1645,7 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index) ...@@ -1645,6 +1645,7 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
//w.add(DictTabInfo::NoOfVariable, (Uint32)0); //w.add(DictTabInfo::NoOfVariable, (Uint32)0);
//w.add(DictTabInfo::KeyLength, 1); //w.add(DictTabInfo::KeyLength, 1);
w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType); w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType);
w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
for (unsigned i = 0; i < table.columnCount; i++) { for (unsigned i = 0; i < table.columnCount; i++) {
const SysColumn& column = table.columnList[i]; const SysColumn& column = table.columnList[i];
......
...@@ -430,6 +430,18 @@ NdbDictionary::Table::getFrmLength() const { ...@@ -430,6 +430,18 @@ NdbDictionary::Table::getFrmLength() const {
return m_impl.m_frm.length(); return m_impl.m_frm.length();
} }
enum NdbDictionary::Table::SingleUserMode
NdbDictionary::Table::getSingleUserMode() const
{
return (enum SingleUserMode)m_impl.m_single_user_mode;
}
void
NdbDictionary::Table::setSingleUserMode(enum NdbDictionary::Table::SingleUserMode mode)
{
m_impl.m_single_user_mode = (Uint8)mode;
}
void void
NdbDictionary::Table::setFrm(const void* data, Uint32 len){ NdbDictionary::Table::setFrm(const void* data, Uint32 len){
m_impl.m_frm.assign(data, len); m_impl.m_frm.assign(data, len);
......
...@@ -318,6 +318,7 @@ NdbTableImpl::init(){ ...@@ -318,6 +318,7 @@ NdbTableImpl::init(){
m_replicaCount= 0; m_replicaCount= 0;
m_min_rows = 0; m_min_rows = 0;
m_max_rows = 0; m_max_rows = 0;
m_single_user_mode = 0;
} }
bool bool
...@@ -378,6 +379,14 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const ...@@ -378,6 +379,14 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
DBUG_RETURN(false); DBUG_RETURN(false);
} }
if(m_single_user_mode != obj.m_single_user_mode)
{
DBUG_PRINT("info",("m_single_user_mode %d != %d",
(int32)m_single_user_mode,
(int32)obj.m_single_user_mode));
DBUG_RETURN(false);
}
DBUG_RETURN(true); DBUG_RETURN(true);
} }
...@@ -403,7 +412,8 @@ NdbTableImpl::assign(const NdbTableImpl& org) ...@@ -403,7 +412,8 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_kvalue = org.m_kvalue; m_kvalue = org.m_kvalue;
m_minLoadFactor = org.m_minLoadFactor; m_minLoadFactor = org.m_minLoadFactor;
m_maxLoadFactor = org.m_maxLoadFactor; m_maxLoadFactor = org.m_maxLoadFactor;
m_single_user_mode = org.m_single_user_mode;
if (m_index != 0) if (m_index != 0)
delete m_index; delete m_index;
m_index = org.m_index; m_index = org.m_index;
...@@ -1191,6 +1201,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, ...@@ -1191,6 +1201,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_kvalue = tableDesc.TableKValue; impl->m_kvalue = tableDesc.TableKValue;
impl->m_minLoadFactor = tableDesc.MinLoadFactor; impl->m_minLoadFactor = tableDesc.MinLoadFactor;
impl->m_maxLoadFactor = tableDesc.MaxLoadFactor; impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
impl->m_single_user_mode = tableDesc.SingleUserMode;
impl->m_indexType = (NdbDictionary::Index::Type) impl->m_indexType = (NdbDictionary::Index::Type)
getApiConstant(tableDesc.TableType, getApiConstant(tableDesc.TableType,
...@@ -1519,12 +1530,14 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, ...@@ -1519,12 +1530,14 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
tmpTab.MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF); tmpTab.MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
tmpTab.MinRowsHigh = (Uint32)(impl.m_min_rows >> 32); tmpTab.MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
tmpTab.MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF); tmpTab.MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
Uint64 maxRows = Uint64 maxRows =
(((Uint64)tmpTab.MaxRowsHigh) << 32) + tmpTab.MaxRowsLow; (((Uint64)tmpTab.MaxRowsHigh) << 32) + tmpTab.MaxRowsLow;
Uint64 minRows = Uint64 minRows =
(((Uint64)tmpTab.MinRowsHigh) << 32) + tmpTab.MinRowsLow; (((Uint64)tmpTab.MinRowsHigh) << 32) + tmpTab.MinRowsLow;
tmpTab.SingleUserMode = impl.m_single_user_mode;
tmpTab.FragmentType = getKernelConstant(impl.m_fragmentType, tmpTab.FragmentType = getKernelConstant(impl.m_fragmentType,
fragmentTypeMapping, fragmentTypeMapping,
DictTabInfo::AllNodesSmallTable); DictTabInfo::AllNodesSmallTable);
......
...@@ -138,6 +138,7 @@ public: ...@@ -138,6 +138,7 @@ public:
int m_maxLoadFactor; int m_maxLoadFactor;
Uint16 m_keyLenInWords; Uint16 m_keyLenInWords;
Uint16 m_fragmentCount; Uint16 m_fragmentCount;
Uint8 m_single_user_mode;
NdbDictionaryImpl * m_dictionary; NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index; NdbIndexImpl * m_index;
......
...@@ -31,7 +31,7 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab) ...@@ -31,7 +31,7 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
ndbout << "Number of attributes: " << tab.getNoOfColumns() << endl; ndbout << "Number of attributes: " << tab.getNoOfColumns() << endl;
ndbout << "Number of primary keys: " << tab.getNoOfPrimaryKeys() << endl; ndbout << "Number of primary keys: " << tab.getNoOfPrimaryKeys() << endl;
ndbout << "Length of frm data: " << tab.getFrmLength() << endl; ndbout << "Length of frm data: " << tab.getFrmLength() << endl;
ndbout << "SingleUserMode: " << tab.getSingleUserMode() << endl;
//<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl; //<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl;
ndbout << "TableStatus: "; ndbout << "TableStatus: ";
......
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