Commit 52e05dad authored by pekka@mysql.com's avatar pekka@mysql.com

ndb: fix bug-4644 Err Out of fragment operations

parent ec025721
...@@ -132,9 +132,10 @@ class TupAddAttrConf { ...@@ -132,9 +132,10 @@ class TupAddAttrConf {
friend class Dblqh; friend class Dblqh;
friend class Dbtup; friend class Dbtup;
public: public:
STATIC_CONST( SignalLength = 1 ); STATIC_CONST( SignalLength = 2 );
private: private:
Uint32 userPtr; Uint32 userPtr;
Uint32 lastAttr; // bool: got last attr and closed frag op
}; };
class TupAddAttrRef { class TupAddAttrRef {
...@@ -171,9 +172,10 @@ class TuxAddAttrConf { ...@@ -171,9 +172,10 @@ class TuxAddAttrConf {
friend class Dblqh; friend class Dblqh;
friend class Dbtux; friend class Dbtux;
public: public:
STATIC_CONST( SignalLength = 1 ); STATIC_CONST( SignalLength = 2 );
private: private:
Uint32 userPtr; Uint32 userPtr;
Uint32 lastAttr; // bool: got last attr and closed frag op
}; };
class TuxAddAttrRef { class TuxAddAttrRef {
......
...@@ -2,7 +2,7 @@ Next QMGR 1 ...@@ -2,7 +2,7 @@ Next QMGR 1
Next NDBCNTR 1000 Next NDBCNTR 1000
Next NDBFS 2000 Next NDBFS 2000
Next DBACC 3001 Next DBACC 3001
Next DBTUP 4007 Next DBTUP 4013
Next DBLQH 5042 Next DBLQH 5042
Next DBDICT 6006 Next DBDICT 6006
Next DBDIH 7174 Next DBDIH 7174
...@@ -10,7 +10,7 @@ Next DBTC 8035 ...@@ -10,7 +10,7 @@ Next DBTC 8035
Next CMVMI 9000 Next CMVMI 9000
Next BACKUP 10022 Next BACKUP 10022
Next DBUTIL 11002 Next DBUTIL 11002
Next DBTUX 12001 Next DBTUX 12007
Next SUMA 13001 Next SUMA 13001
TESTING NODE FAILURE, ARBITRATION TESTING NODE FAILURE, ARBITRATION
...@@ -393,6 +393,12 @@ Failed Create Table: ...@@ -393,6 +393,12 @@ Failed Create Table:
-------------------- --------------------
7173: Create table failed due to not sufficient number of fragment or 7173: Create table failed due to not sufficient number of fragment or
replica records. replica records.
4007 12001: Fail create 1st fragment
4008 12002: Fail create 2nd fragment
4009 12003: Fail create 1st attribute in 1st fragment
4010 12004: Fail create last attribute in 1st fragment
4011 12005: Fail create 1st attribute in 2nd fragment
4012 12006: Fail create last attribute in 2nd fragment
Drop Table/Index: Drop Table/Index:
----------------- -----------------
......
...@@ -2474,7 +2474,7 @@ private: ...@@ -2474,7 +2474,7 @@ private:
void sendExecFragRefLab(Signal* signal); void sendExecFragRefLab(Signal* signal);
void fragrefLab(Signal* signal, BlockReference retRef, void fragrefLab(Signal* signal, BlockReference retRef,
Uint32 retPtr, Uint32 errorCode); Uint32 retPtr, Uint32 errorCode);
void accFragRefLab(Signal* signal); void abortAddFragOps(Signal* signal);
void rwConcludedLab(Signal* signal); void rwConcludedLab(Signal* signal);
void sendsttorryLab(Signal* signal); void sendsttorryLab(Signal* signal);
void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32); void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32);
......
...@@ -912,6 +912,10 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal) ...@@ -912,6 +912,10 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
/* *********************************************************> */ /* *********************************************************> */
/* LQHFRAGREQ: Create new fragments for a table. Sender DICT */ /* LQHFRAGREQ: Create new fragments for a table. Sender DICT */
/* *********************************************************> */ /* *********************************************************> */
// this unbelievable mess could be replaced by one signal to LQH
// and execute direct to local DICT to get everything at once
void Dblqh::execLQHFRAGREQ(Signal* signal) void Dblqh::execLQHFRAGREQ(Signal* signal)
{ {
jamEntry(); jamEntry();
...@@ -1049,6 +1053,11 @@ void Dblqh::execLQHFRAGREQ(Signal* signal) ...@@ -1049,6 +1053,11 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->lh3DistrBits = tlhstar; addfragptr.p->lh3DistrBits = tlhstar;
addfragptr.p->tableType = tableType; addfragptr.p->tableType = tableType;
addfragptr.p->primaryTableId = primaryTableId; addfragptr.p->primaryTableId = primaryTableId;
//
addfragptr.p->tup1Connectptr = RNIL;
addfragptr.p->tup2Connectptr = RNIL;
addfragptr.p->tux1Connectptr = RNIL;
addfragptr.p->tux2Connectptr = RNIL;
if (DictTabInfo::isTable(tableType) || if (DictTabInfo::isTable(tableType) ||
DictTabInfo::isHashIndex(tableType)) { DictTabInfo::isHashIndex(tableType)) {
...@@ -1329,15 +1338,21 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal) ...@@ -1329,15 +1338,21 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
{ {
jamEntry(); jamEntry();
addfragptr.i = signal->theData[0]; addfragptr.i = signal->theData[0];
// implies that operation was released on the other side
const bool lastAttr = signal->theData[1];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord); ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
switch (addfragptr.p->addfragStatus) { switch (addfragptr.p->addfragStatus) {
case AddFragRecord::TUP_ATTR_WAIT1: case AddFragRecord::TUP_ATTR_WAIT1:
jam(); jam();
if (lastAttr)
addfragptr.p->tup1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT2; addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT2;
sendAddAttrReq(signal); sendAddAttrReq(signal);
break; break;
case AddFragRecord::TUP_ATTR_WAIT2: case AddFragRecord::TUP_ATTR_WAIT2:
jam(); jam();
if (lastAttr)
addfragptr.p->tup2Connectptr = RNIL;
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) { if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT1; addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT1;
sendAddAttrReq(signal); sendAddAttrReq(signal);
...@@ -1347,11 +1362,15 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal) ...@@ -1347,11 +1362,15 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
break; break;
case AddFragRecord::TUX_ATTR_WAIT1: case AddFragRecord::TUX_ATTR_WAIT1:
jam(); jam();
if (lastAttr)
addfragptr.p->tux1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT2; addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT2;
sendAddAttrReq(signal); sendAddAttrReq(signal);
break; break;
case AddFragRecord::TUX_ATTR_WAIT2: case AddFragRecord::TUX_ATTR_WAIT2:
jam(); jam();
if (lastAttr)
addfragptr.p->tux2Connectptr = RNIL;
goto done_with_attr; goto done_with_attr;
break; break;
done_with_attr: done_with_attr:
...@@ -1455,6 +1474,7 @@ Dblqh::sendAddAttrReq(Signal* signal) ...@@ -1455,6 +1474,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam(); jam();
TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend(); TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
tupconf->userPtr = addfragptr.i; tupconf->userPtr = addfragptr.i;
tupconf->lastAttr = false;
sendSignal(reference(), GSN_TUP_ADD_ATTCONF, sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
signal, TupAddAttrConf::SignalLength, JBB); signal, TupAddAttrConf::SignalLength, JBB);
return; return;
...@@ -1485,6 +1505,7 @@ Dblqh::sendAddAttrReq(Signal* signal) ...@@ -1485,6 +1505,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam(); jam();
TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend(); TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
tuxconf->userPtr = addfragptr.i; tuxconf->userPtr = addfragptr.i;
tuxconf->lastAttr = false;
sendSignal(reference(), GSN_TUX_ADD_ATTRCONF, sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB); signal, TuxAddAttrConf::SignalLength, JBB);
return; return;
...@@ -1549,6 +1570,40 @@ void Dblqh::fragrefLab(Signal* signal, ...@@ -1549,6 +1570,40 @@ void Dblqh::fragrefLab(Signal* signal,
return; return;
}//Dblqh::fragrefLab() }//Dblqh::fragrefLab()
/*
* Abort on-going ops.
*/
void Dblqh::abortAddFragOps(Signal* signal)
{
fragptr.i = addfragptr.p->fragmentPtr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
signal->theData[0] = (Uint32)-1;
if (addfragptr.p->tup1Connectptr != RNIL) {
jam();
signal->theData[1] = addfragptr.p->tup1Connectptr;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
addfragptr.p->tup1Connectptr = RNIL;
}
if (addfragptr.p->tup2Connectptr != RNIL) {
jam();
signal->theData[1] = addfragptr.p->tup2Connectptr;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
addfragptr.p->tup2Connectptr = RNIL;
}
if (addfragptr.p->tux1Connectptr != RNIL) {
jam();
signal->theData[1] = addfragptr.p->tux1Connectptr;
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
addfragptr.p->tux1Connectptr = RNIL;
}
if (addfragptr.p->tux2Connectptr != RNIL) {
jam();
signal->theData[1] = addfragptr.p->tux2Connectptr;
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
addfragptr.p->tux2Connectptr = RNIL;
}
}
/* ************>> */ /* ************>> */
/* ACCFRAGREF > */ /* ACCFRAGREF > */
/* ************>> */ /* ************>> */
...@@ -1582,6 +1637,27 @@ void Dblqh::execTUPFRAGREF(Signal* signal) ...@@ -1582,6 +1637,27 @@ void Dblqh::execTUPFRAGREF(Signal* signal)
fragptr.i = addfragptr.p->fragmentPtr; fragptr.i = addfragptr.p->fragmentPtr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord); ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
addfragptr.p->addfragErrorCode = terrorCode; addfragptr.p->addfragErrorCode = terrorCode;
// no operation to release, just add some jams
switch (addfragptr.p->addfragStatus) {
case AddFragRecord::WAIT_TWO_TUP:
jam();
break;
case AddFragRecord::WAIT_ONE_TUP:
jam();
break;
case AddFragRecord::WAIT_TWO_TUX:
jam();
break;
case AddFragRecord::WAIT_ONE_TUX:
jam();
break;
default:
ndbrequire(false);
break;
}
abortAddFragOps(signal);
const Uint32 ref = addfragptr.p->dictBlockref; const Uint32 ref = addfragptr.p->dictBlockref;
const Uint32 senderData = addfragptr.p->dictConnectptr; const Uint32 senderData = addfragptr.p->dictConnectptr;
const Uint32 errorCode = addfragptr.p->addfragErrorCode; const Uint32 errorCode = addfragptr.p->addfragErrorCode;
...@@ -1605,11 +1681,38 @@ void Dblqh::execTUXFRAGREF(Signal* signal) ...@@ -1605,11 +1681,38 @@ void Dblqh::execTUXFRAGREF(Signal* signal)
void Dblqh::execTUP_ADD_ATTRREF(Signal* signal) void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
{ {
jamEntry(); jamEntry();
addfragptr.i = signal->theData[0]; addfragptr.i = signal->theData[0];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord); ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
terrorCode = signal->theData[1]; terrorCode = signal->theData[1];
addfragptr.p->addfragErrorCode = terrorCode; addfragptr.p->addfragErrorCode = terrorCode;
// operation was released on the other side
switch (addfragptr.p->addfragStatus) {
case AddFragRecord::TUP_ATTR_WAIT1:
jam();
ndbrequire(addfragptr.p->tup1Connectptr != RNIL);
addfragptr.p->tup1Connectptr = RNIL;
break;
case AddFragRecord::TUP_ATTR_WAIT2:
jam();
ndbrequire(addfragptr.p->tup2Connectptr != RNIL);
addfragptr.p->tup2Connectptr = RNIL;
break;
case AddFragRecord::TUX_ATTR_WAIT1:
jam();
ndbrequire(addfragptr.p->tux1Connectptr != RNIL);
addfragptr.p->tux1Connectptr = RNIL;
break;
case AddFragRecord::TUX_ATTR_WAIT2:
jam();
ndbrequire(addfragptr.p->tux2Connectptr != RNIL);
addfragptr.p->tux2Connectptr = RNIL;
break;
default:
ndbrequire(false);
break;
}
abortAddFragOps(signal);
const Uint32 Ref = addfragptr.p->dictBlockref; const Uint32 Ref = addfragptr.p->dictBlockref;
const Uint32 senderData = addfragptr.p->dictConnectptr; const Uint32 senderData = addfragptr.p->dictConnectptr;
......
...@@ -504,6 +504,7 @@ struct Fragoperrec { ...@@ -504,6 +504,7 @@ struct Fragoperrec {
Uint32 noOfNewAttrCount; Uint32 noOfNewAttrCount;
Uint32 charsetIndex; Uint32 charsetIndex;
BlockReference lqhBlockrefFrag; BlockReference lqhBlockrefFrag;
bool inUse;
}; };
typedef Ptr<Fragoperrec> FragoperrecPtr; typedef Ptr<Fragoperrec> FragoperrecPtr;
...@@ -1936,6 +1937,7 @@ private: ...@@ -1936,6 +1937,7 @@ private:
void setUpKeyArray(Tablerec* const regTabPtr); void setUpKeyArray(Tablerec* const regTabPtr);
bool addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex); bool addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex);
void deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId); void deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId);
void abortAddFragOp(Signal* signal);
void releaseTabDescr(Tablerec* const regTabPtr); void releaseTabDescr(Tablerec* const regTabPtr);
void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr); void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr);
......
...@@ -39,11 +39,18 @@ ...@@ -39,11 +39,18 @@
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
void Dbtup::execTUPFRAGREQ(Signal* signal) void Dbtup::execTUPFRAGREQ(Signal* signal)
{ {
ljamEntry();
if (signal->theData[0] == (Uint32)-1) {
ljam();
abortAddFragOp(signal);
return;
}
FragoperrecPtr fragOperPtr; FragoperrecPtr fragOperPtr;
FragrecordPtr regFragPtr; FragrecordPtr regFragPtr;
TablerecPtr regTabPtr; TablerecPtr regTabPtr;
ljamEntry();
Uint32 userptr = signal->theData[0]; Uint32 userptr = signal->theData[0];
Uint32 userblockref = signal->theData[1]; Uint32 userblockref = signal->theData[1];
Uint32 reqinfo = signal->theData[2]; Uint32 reqinfo = signal->theData[2];
...@@ -132,6 +139,15 @@ void Dbtup::execTUPFRAGREQ(Signal* signal) ...@@ -132,6 +139,15 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
return; return;
}//if }//if
if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
ljam();
terrorCode = 1;
fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
CLEAR_ERROR_INSERT_VALUE;
return;
}
if (regTabPtr.p->tableStatus == NOT_DEFINED) { if (regTabPtr.p->tableStatus == NOT_DEFINED) {
ljam(); ljam();
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
...@@ -243,6 +259,7 @@ void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr) ...@@ -243,6 +259,7 @@ void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec); ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
cfirstfreeFragopr = fragOperPtr.p->nextFragoprec; cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
fragOperPtr.p->nextFragoprec = RNIL; fragOperPtr.p->nextFragoprec = RNIL;
fragOperPtr.p->inUse = true;
}//Dbtup::seizeFragoperrec() }//Dbtup::seizeFragoperrec()
/* **************************************************************** */ /* **************************************************************** */
...@@ -273,6 +290,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal) ...@@ -273,6 +290,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ndbrequire(fragOperPtr.p->attributeCount > 0); ndbrequire(fragOperPtr.p->attributeCount > 0);
fragOperPtr.p->attributeCount--; fragOperPtr.p->attributeCount--;
const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
if ((regTabPtr.p->tableStatus == DEFINING) && if ((regTabPtr.p->tableStatus == DEFINING) &&
(fragOperPtr.p->definingFragment)) { (fragOperPtr.p->definingFragment)) {
...@@ -346,20 +364,30 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal) ...@@ -346,20 +364,30 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId); addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return; return;
}//if }//if
if ((fragOperPtr.p->attributeCount == 0) && if (lastAttr && (fragOperPtr.p->freeNullBit != 0)) {
(fragOperPtr.p->freeNullBit != 0)) {
ljam(); ljam();
terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT; terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId); addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return; return;
}//if }//if
}//if }//if
if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0 ||
ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0 ||
ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
ljam();
terrorCode = 1;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
CLEAR_ERROR_INSERT_VALUE;
return;
}
/* **************************************************************** */ /* **************************************************************** */
/* ************** TUP_ADD_ATTCONF ****************** */ /* ************** TUP_ADD_ATTCONF ****************** */
/* **************************************************************** */ /* **************************************************************** */
signal->theData[0] = fragOperPtr.p->lqhPtrFrag; signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 1, JBB); signal->theData[1] = lastAttr;
if (fragOperPtr.p->attributeCount > 0) { sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 2, JBB);
if (! lastAttr) {
ljam(); ljam();
return; /* EXIT AND WAIT FOR MORE */ return; /* EXIT AND WAIT FOR MORE */
}//if }//if
...@@ -491,11 +519,11 @@ void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr) ...@@ -491,11 +519,11 @@ void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr)
void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr) void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
{ {
fragOperPtr.p->inUse = false;
fragOperPtr.p->nextFragoprec = cfirstfreeFragopr; fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
cfirstfreeFragopr = fragOperPtr.i; cfirstfreeFragopr = fragOperPtr.i;
}//Dbtup::releaseFragoperrec() }//Dbtup::releaseFragoperrec()
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId) void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
{ {
for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) { for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
...@@ -510,6 +538,20 @@ void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId) ...@@ -510,6 +538,20 @@ void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
ndbrequire(false); ndbrequire(false);
}//Dbtup::deleteFragTab() }//Dbtup::deleteFragTab()
/*
* LQH aborts on-going create table operation. The table is later
* dropped by DICT.
*/
void Dbtup::abortAddFragOp(Signal* signal)
{
FragoperrecPtr fragOperPtr;
fragOperPtr.i = signal->theData[1];
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
ndbrequire(fragOperPtr.p->inUse);
releaseFragoperrec(fragOperPtr);
}
void void
Dbtup::execDROP_TAB_REQ(Signal* signal) Dbtup::execDROP_TAB_REQ(Signal* signal)
{ {
......
...@@ -575,6 +575,7 @@ private: ...@@ -575,6 +575,7 @@ private:
void execDROP_TAB_REQ(Signal* signal); void execDROP_TAB_REQ(Signal* signal);
bool allocDescEnt(IndexPtr indexPtr); bool allocDescEnt(IndexPtr indexPtr);
void freeDescEnt(IndexPtr indexPtr); void freeDescEnt(IndexPtr indexPtr);
void abortAddFragOp(Signal* signal);
void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData); void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
/* /*
...@@ -684,6 +685,7 @@ private: ...@@ -684,6 +685,7 @@ private:
friend class NdbOut& operator<<(NdbOut&, const ScanOp&); friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
friend class NdbOut& operator<<(NdbOut&, const Index&); friend class NdbOut& operator<<(NdbOut&, const Index&);
friend class NdbOut& operator<<(NdbOut&, const Frag&); friend class NdbOut& operator<<(NdbOut&, const Frag&);
friend class NdbOut& operator<<(NdbOut&, const FragOp&);
friend class NdbOut& operator<<(NdbOut&, const NodeHandle&); friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
FILE* debugFile; FILE* debugFile;
NdbOut debugOut; NdbOut debugOut;
......
...@@ -403,6 +403,19 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag) ...@@ -403,6 +403,19 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
return out; return out;
} }
NdbOut&
operator<<(NdbOut& out, const Dbtux::FragOp& fragOp)
{
out << "[FragOp " << hex << &fragOp;
out << " [userPtr " << dec << fragOp.m_userPtr << "]";
out << " [indexId " << dec << fragOp.m_indexId << "]";
out << " [fragId " << dec << fragOp.m_fragId << "]";
out << " [fragNo " << dec << fragOp.m_fragNo << "]";
out << " numAttrsRecvd " << dec << fragOp.m_numAttrsRecvd << "]";
out << "]";
return out;
}
NdbOut& NdbOut&
operator<<(NdbOut& out, const Dbtux::NodeHandle& node) operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
{ {
......
...@@ -24,12 +24,7 @@ Dbtux::Dbtux(const Configuration& conf) : ...@@ -24,12 +24,7 @@ Dbtux::Dbtux(const Configuration& conf) :
#ifdef VM_TRACE #ifdef VM_TRACE
debugFile(0), debugFile(0),
debugOut(*new NullOutputStream()), debugOut(*new NullOutputStream()),
// until ndb_mgm supports dump
#ifdef DBTUX_DEBUG_TREE
debugFlags(DebugTree),
#else
debugFlags(0), debugFlags(0),
#endif
#endif #endif
c_internalStartPhase(0), c_internalStartPhase(0),
c_typeOfStart(NodeState::ST_ILLEGAL_TYPE), c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
...@@ -86,7 +81,7 @@ Dbtux::execCONTINUEB(Signal* signal) ...@@ -86,7 +81,7 @@ Dbtux::execCONTINUEB(Signal* signal)
jamEntry(); jamEntry();
const Uint32* data = signal->getDataPtr(); const Uint32* data = signal->getDataPtr();
switch (data[0]) { switch (data[0]) {
case TuxContinueB::DropIndex: case TuxContinueB::DropIndex: // currently unused
{ {
IndexPtr indexPtr; IndexPtr indexPtr;
c_indexPool.getPtr(indexPtr, data[1]); c_indexPool.getPtr(indexPtr, data[1]);
...@@ -174,7 +169,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal) ...@@ -174,7 +169,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
const Uint32 nDescPage = (nIndex + nAttribute + DescPageSize - 1) / DescPageSize; const Uint32 nDescPage = (nIndex * DescHeadSize + nAttribute * DescAttrSize + DescPageSize - 1) / DescPageSize;
const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4; const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4;
c_indexPool.setSize(nIndex); c_indexPool.setSize(nIndex);
......
...@@ -29,6 +29,11 @@ void ...@@ -29,6 +29,11 @@ void
Dbtux::execTUXFRAGREQ(Signal* signal) Dbtux::execTUXFRAGREQ(Signal* signal)
{ {
jamEntry(); jamEntry();
if (signal->theData[0] == (Uint32)-1) {
jam();
abortAddFragOp(signal);
return;
}
const TuxFragReq reqCopy = *(const TuxFragReq*)signal->getDataPtr(); const TuxFragReq reqCopy = *(const TuxFragReq*)signal->getDataPtr();
const TuxFragReq* const req = &reqCopy; const TuxFragReq* const req = &reqCopy;
IndexPtr indexPtr; IndexPtr indexPtr;
...@@ -61,6 +66,11 @@ Dbtux::execTUXFRAGREQ(Signal* signal) ...@@ -61,6 +66,11 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragOpPtr.p->m_fragId = req->fragId; fragOpPtr.p->m_fragId = req->fragId;
fragOpPtr.p->m_fragNo = indexPtr.p->m_numFrags; fragOpPtr.p->m_fragNo = indexPtr.p->m_numFrags;
fragOpPtr.p->m_numAttrsRecvd = 0; fragOpPtr.p->m_numAttrsRecvd = 0;
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Seize frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
// check if index has place for more fragments // check if index has place for more fragments
ndbrequire(indexPtr.p->m_numFrags < MaxIndexFragments); ndbrequire(indexPtr.p->m_numFrags < MaxIndexFragments);
// seize new fragment record // seize new fragment record
...@@ -129,6 +139,14 @@ Dbtux::execTUXFRAGREQ(Signal* signal) ...@@ -129,6 +139,14 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
debugOut << "Add frag " << fragPtr.i << " " << *fragPtr.p << endl; debugOut << "Add frag " << fragPtr.i << " " << *fragPtr.p << endl;
} }
#endif #endif
// error inserts
if (ERROR_INSERTED(12001) && fragOpPtr.p->m_fragNo == 0 ||
ERROR_INSERTED(12002) && fragOpPtr.p->m_fragNo == 1) {
jam();
errorCode = (TuxFragRef::ErrorCode)1;
CLEAR_ERROR_INSERT_VALUE;
break;
}
// success // success
TuxFragConf* const conf = (TuxFragConf*)signal->getDataPtrSend(); TuxFragConf* const conf = (TuxFragConf*)signal->getDataPtrSend();
conf->userPtr = req->userPtr; conf->userPtr = req->userPtr;
...@@ -145,10 +163,18 @@ Dbtux::execTUXFRAGREQ(Signal* signal) ...@@ -145,10 +163,18 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
ref->errorCode = errorCode; ref->errorCode = errorCode;
sendSignal(req->userRef, GSN_TUXFRAGREF, sendSignal(req->userRef, GSN_TUXFRAGREF,
signal, TuxFragRef::SignalLength, JBB); signal, TuxFragRef::SignalLength, JBB);
if (fragOpPtr.i != RNIL) if (fragOpPtr.i != RNIL) {
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Release on frag error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
c_fragOpPool.release(fragOpPtr); c_fragOpPool.release(fragOpPtr);
if (indexPtr.i != RNIL) }
dropIndex(signal, indexPtr, 0, 0); if (indexPtr.i != RNIL) {
jam();
// let DICT drop the unfinished index
}
} }
void void
...@@ -203,7 +229,16 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal) ...@@ -203,7 +229,16 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
} }
} }
#endif #endif
if (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd) { const bool lastAttr = (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd);
if (ERROR_INSERTED(12003) && fragOpPtr.p->m_fragNo == 0 && attrId == 0 ||
ERROR_INSERTED(12004) && fragOpPtr.p->m_fragNo == 0 && lastAttr ||
ERROR_INSERTED(12005) && fragOpPtr.p->m_fragNo == 1 && attrId == 0 ||
ERROR_INSERTED(12006) && fragOpPtr.p->m_fragNo == 1 && lastAttr) {
errorCode = (TuxAddAttrRef::ErrorCode)1;
CLEAR_ERROR_INSERT_VALUE;
break;
}
if (lastAttr) {
jam(); jam();
// initialize tree header // initialize tree header
TreeHead& tree = fragPtr.p->m_tree; TreeHead& tree = fragPtr.p->m_tree;
...@@ -246,11 +281,17 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal) ...@@ -246,11 +281,17 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
} }
#endif #endif
// fragment is defined // fragment is defined
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Release frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
c_fragOpPool.release(fragOpPtr); c_fragOpPool.release(fragOpPtr);
} }
// success // success
TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend(); TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend();
conf->userPtr = fragOpPtr.p->m_userPtr; conf->userPtr = fragOpPtr.p->m_userPtr;
conf->lastAttr = lastAttr;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF, sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB); signal, TuxAddAttrConf::SignalLength, JBB);
return; return;
...@@ -261,8 +302,32 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal) ...@@ -261,8 +302,32 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
ref->errorCode = errorCode; ref->errorCode = errorCode;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF, sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF,
signal, TuxAddAttrRef::SignalLength, JBB); signal, TuxAddAttrRef::SignalLength, JBB);
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Release on attr error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
c_fragOpPool.release(fragOpPtr); c_fragOpPool.release(fragOpPtr);
dropIndex(signal, indexPtr, 0, 0); // let DICT drop the unfinished index
}
/*
* LQH aborts on-going create index operation.
*/
void
Dbtux::abortAddFragOp(Signal* signal)
{
FragOpPtr fragOpPtr;
IndexPtr indexPtr;
c_fragOpPool.getPtr(fragOpPtr, signal->theData[1]);
c_indexPool.getPtr(indexPtr, fragOpPtr.p->m_indexId);
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Release on abort frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
c_fragOpPool.release(fragOpPtr);
// let DICT drop the unfinished index
} }
/* /*
...@@ -341,20 +406,13 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen ...@@ -341,20 +406,13 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen
{ {
jam(); jam();
indexPtr.p->m_state = Index::Dropping; indexPtr.p->m_state = Index::Dropping;
// drop one fragment at a time // drop fragments
if (indexPtr.p->m_numFrags > 0) { while (indexPtr.p->m_numFrags > 0) {
jam(); jam();
unsigned i = --indexPtr.p->m_numFrags; Uint32 i = --indexPtr.p->m_numFrags;
FragPtr fragPtr; FragPtr fragPtr;
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]); c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
c_fragPool.release(fragPtr); c_fragPool.release(fragPtr);
// the real time break is not used for anything currently
signal->theData[0] = TuxContinueB::DropIndex;
signal->theData[1] = indexPtr.i;
signal->theData[2] = senderRef;
signal->theData[3] = senderData;
sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
return;
} }
// drop attributes // drop attributes
if (indexPtr.p->m_descPage != RNIL) { if (indexPtr.p->m_descPage != RNIL) {
......
...@@ -1479,6 +1479,69 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -1479,6 +1479,69 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK; return NDBT_OK;
} }
int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
static int tuplst[] = { 4007, 4008, 4009, 4010, 4011, 4012 };
static int tuxlst[] = { 12001, 12002, 12003, 12004, 12005, 12006 };
static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
NdbRestarter restarter;
int nodeId = restarter.getMasterNodeId();
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
NdbDictionary::Table tab(*ctx->getTab());
tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
// ordered index on first few columns
NdbDictionary::Index idx("X");
idx.setTable(tab.getName());
idx.setType(NdbDictionary::Index::OrderedIndex);
idx.setLogging(false);
for (int i_hate_broken_compilers = 0;
i_hate_broken_compilers < 3 &&
i_hate_broken_compilers < tab.getNoOfColumns();
i_hate_broken_compilers++) {
idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
}
const int loops = ctx->getNumLoops();
int result = NDBT_OK;
(void)pDic->dropTable(tab.getName());
for (int l = 0; l < loops; l++) {
for (unsigned i = 0; i < tupcnt; i++) {
unsigned j = (l == 0 ? i : myRandom48(tupcnt));
int errval = tuplst[j];
g_info << "insert error node=" << nodeId << " value=" << errval << endl;
CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
"failed to set error insert");
CHECK2(pDic->createTable(tab) != 0,
"failed to fail after error insert " << errval);
CHECK2(pDic->createTable(tab) == 0,
pDic->getNdbError());
CHECK2(pDic->dropTable(tab.getName()) == 0,
pDic->getNdbError());
}
for (unsigned i = 0; i < tuxcnt; i++) {
unsigned j = (l == 0 ? i : myRandom48(tuxcnt));
int errval = tuxlst[j];
g_info << "insert error node=" << nodeId << " value=" << errval << endl;
CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
"failed to set error insert");
CHECK2(pDic->createTable(tab) == 0,
pDic->getNdbError());
CHECK2(pDic->createIndex(idx) != 0,
"failed to fail after error insert " << errval);
CHECK2(pDic->createIndex(idx) == 0,
pDic->getNdbError());
CHECK2(pDic->dropTable(tab.getName()) == 0,
pDic->getNdbError());
}
}
end:
return result;
}
NDBT_TESTSUITE(testDict); NDBT_TESTSUITE(testDict);
TESTCASE("CreateAndDrop", TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){ "Try to create and drop the table loop number of times\n"){
...@@ -1574,6 +1637,10 @@ TESTCASE("DictionaryPerf", ...@@ -1574,6 +1637,10 @@ TESTCASE("DictionaryPerf",
""){ ""){
INITIALIZER(runTestDictionaryPerf); INITIALIZER(runTestDictionaryPerf);
} }
TESTCASE("FailAddFragment",
"Fail add fragment or attribute in TUP or TUX\n"){
INITIALIZER(runFailAddFragment);
}
NDBT_TESTSUITE_END(testDict); NDBT_TESTSUITE_END(testDict);
int main(int argc, const char** argv){ int main(int argc, const char** argv){
......
...@@ -2144,22 +2144,19 @@ void ha_ndbcluster::print_results() ...@@ -2144,22 +2144,19 @@ void ha_ndbcluster::print_results()
} }
case NdbDictionary::Column::Decimal: { case NdbDictionary::Column::Decimal: {
char *value= field->ptr; char *value= field->ptr;
fprintf(DBUG_FILE, "Decimal\t'%-*s'", field->pack_length(), value); fprintf(DBUG_FILE, "Decimal\t'%-*s'", field->pack_length(), value);
break; break;
} }
case NdbDictionary::Column::Char:{ case NdbDictionary::Column::Char:{
char buf[field->pack_length()+1]; const char *value= (char *) field->ptr;
char *value= (char *) field->ptr; fprintf(DBUG_FILE, "Char\t'%.*s'", field->pack_length(), value);
snprintf(buf, field->pack_length(), "%s", value);
fprintf(DBUG_FILE, "Char\t'%s'", buf);
break; break;
} }
case NdbDictionary::Column::Varchar: case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Binary: case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Varbinary: { case NdbDictionary::Column::Varbinary: {
char *value= (char *) field->ptr; const char *value= (char *) field->ptr;
fprintf(DBUG_FILE, "'%s'", value); fprintf(DBUG_FILE, "Var\t'%.*s'", field->pack_length(), value);
break; break;
} }
case NdbDictionary::Column::Datetime: { case NdbDictionary::Column::Datetime: {
......
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