Commit 7a7ee30c authored by unknown's avatar unknown

ndb: fix bug-4644 Err Out of fragment operations


sql/ha_ndbcluster.cc:
  compile fix in DBUG code
ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp:
  fix count of metadata pages
ndb/include/kernel/signaldata/TupFrag.hpp:
  bug-4644 fix
ndb/src/kernel/blocks/ERROR_codes.txt:
  bug-4644 fix
ndb/src/kernel/blocks/dblqh/Dblqh.hpp:
  bug-4644 fix
ndb/src/kernel/blocks/dblqh/DblqhMain.cpp:
  bug-4644 fix
ndb/src/kernel/blocks/dbtup/Dbtup.hpp:
  bug-4644 fix
ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp:
  bug-4644 fix
ndb/src/kernel/blocks/dbtux/Dbtux.hpp:
  bug-4644 fix
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp:
  bug-4644 fix
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp:
  bug-4644 fix
ndb/test/ndbapi/testDict.cpp:
  bug-4644 fix
parent 4374aaa5
......@@ -132,9 +132,10 @@ class TupAddAttrConf {
friend class Dblqh;
friend class Dbtup;
public:
STATIC_CONST( SignalLength = 1 );
STATIC_CONST( SignalLength = 2 );
private:
Uint32 userPtr;
Uint32 lastAttr; // bool: got last attr and closed frag op
};
class TupAddAttrRef {
......@@ -171,9 +172,10 @@ class TuxAddAttrConf {
friend class Dblqh;
friend class Dbtux;
public:
STATIC_CONST( SignalLength = 1 );
STATIC_CONST( SignalLength = 2 );
private:
Uint32 userPtr;
Uint32 lastAttr; // bool: got last attr and closed frag op
};
class TuxAddAttrRef {
......
......@@ -2,7 +2,7 @@ Next QMGR 1
Next NDBCNTR 1000
Next NDBFS 2000
Next DBACC 3001
Next DBTUP 4007
Next DBTUP 4013
Next DBLQH 5042
Next DBDICT 6006
Next DBDIH 7174
......@@ -10,7 +10,7 @@ Next DBTC 8035
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
Next DBTUX 12001
Next DBTUX 12007
Next SUMA 13001
TESTING NODE FAILURE, ARBITRATION
......@@ -393,6 +393,12 @@ Failed Create Table:
--------------------
7173: Create table failed due to not sufficient number of fragment or
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:
-----------------
......
......@@ -2474,7 +2474,7 @@ private:
void sendExecFragRefLab(Signal* signal);
void fragrefLab(Signal* signal, BlockReference retRef,
Uint32 retPtr, Uint32 errorCode);
void accFragRefLab(Signal* signal);
void abortAddFragOps(Signal* signal);
void rwConcludedLab(Signal* signal);
void sendsttorryLab(Signal* signal);
void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32);
......
......@@ -912,6 +912,10 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
/* *********************************************************> */
/* 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)
{
jamEntry();
......@@ -1049,6 +1053,11 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->lh3DistrBits = tlhstar;
addfragptr.p->tableType = tableType;
addfragptr.p->primaryTableId = primaryTableId;
//
addfragptr.p->tup1Connectptr = RNIL;
addfragptr.p->tup2Connectptr = RNIL;
addfragptr.p->tux1Connectptr = RNIL;
addfragptr.p->tux2Connectptr = RNIL;
if (DictTabInfo::isTable(tableType) ||
DictTabInfo::isHashIndex(tableType)) {
......@@ -1329,15 +1338,21 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
{
jamEntry();
addfragptr.i = signal->theData[0];
// implies that operation was released on the other side
const bool lastAttr = signal->theData[1];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
switch (addfragptr.p->addfragStatus) {
case AddFragRecord::TUP_ATTR_WAIT1:
jam();
if (lastAttr)
addfragptr.p->tup1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT2;
sendAddAttrReq(signal);
break;
case AddFragRecord::TUP_ATTR_WAIT2:
jam();
if (lastAttr)
addfragptr.p->tup2Connectptr = RNIL;
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT1;
sendAddAttrReq(signal);
......@@ -1347,11 +1362,15 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
break;
case AddFragRecord::TUX_ATTR_WAIT1:
jam();
if (lastAttr)
addfragptr.p->tux1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT2;
sendAddAttrReq(signal);
break;
case AddFragRecord::TUX_ATTR_WAIT2:
jam();
if (lastAttr)
addfragptr.p->tux2Connectptr = RNIL;
goto done_with_attr;
break;
done_with_attr:
......@@ -1455,6 +1474,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam();
TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
tupconf->userPtr = addfragptr.i;
tupconf->lastAttr = false;
sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
signal, TupAddAttrConf::SignalLength, JBB);
return;
......@@ -1485,6 +1505,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam();
TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
tuxconf->userPtr = addfragptr.i;
tuxconf->lastAttr = false;
sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB);
return;
......@@ -1549,6 +1570,40 @@ void Dblqh::fragrefLab(Signal* signal,
return;
}//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 > */
/* ************>> */
......@@ -1582,6 +1637,27 @@ void Dblqh::execTUPFRAGREF(Signal* signal)
fragptr.i = addfragptr.p->fragmentPtr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
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 senderData = addfragptr.p->dictConnectptr;
const Uint32 errorCode = addfragptr.p->addfragErrorCode;
......@@ -1605,12 +1681,39 @@ void Dblqh::execTUXFRAGREF(Signal* signal)
void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
{
jamEntry();
addfragptr.i = signal->theData[0];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
terrorCode = signal->theData[1];
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 senderData = addfragptr.p->dictConnectptr;
const Uint32 errorCode = addfragptr.p->addfragErrorCode;
......
......@@ -504,6 +504,7 @@ struct Fragoperrec {
Uint32 noOfNewAttrCount;
Uint32 charsetIndex;
BlockReference lqhBlockrefFrag;
bool inUse;
};
typedef Ptr<Fragoperrec> FragoperrecPtr;
......@@ -1936,6 +1937,7 @@ private:
void setUpKeyArray(Tablerec* const regTabPtr);
bool addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex);
void deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId);
void abortAddFragOp(Signal* signal);
void releaseTabDescr(Tablerec* const regTabPtr);
void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr);
......
......@@ -39,11 +39,18 @@
/* ---------------------------------------------------------------- */
void Dbtup::execTUPFRAGREQ(Signal* signal)
{
ljamEntry();
if (signal->theData[0] == (Uint32)-1) {
ljam();
abortAddFragOp(signal);
return;
}
FragoperrecPtr fragOperPtr;
FragrecordPtr regFragPtr;
TablerecPtr regTabPtr;
ljamEntry();
Uint32 userptr = signal->theData[0];
Uint32 userblockref = signal->theData[1];
Uint32 reqinfo = signal->theData[2];
......@@ -132,6 +139,15 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
return;
}//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) {
ljam();
//-------------------------------------------------------------------------------------
......@@ -243,6 +259,7 @@ void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
fragOperPtr.p->nextFragoprec = RNIL;
fragOperPtr.p->inUse = true;
}//Dbtup::seizeFragoperrec()
/* **************************************************************** */
......@@ -273,6 +290,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ndbrequire(fragOperPtr.p->attributeCount > 0);
fragOperPtr.p->attributeCount--;
const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
if ((regTabPtr.p->tableStatus == DEFINING) &&
(fragOperPtr.p->definingFragment)) {
......@@ -346,20 +364,30 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//if
if ((fragOperPtr.p->attributeCount == 0) &&
(fragOperPtr.p->freeNullBit != 0)) {
if (lastAttr && (fragOperPtr.p->freeNullBit != 0)) {
ljam();
terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//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 ****************** */
/* **************************************************************** */
signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 1, JBB);
if (fragOperPtr.p->attributeCount > 0) {
signal->theData[1] = lastAttr;
sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 2, JBB);
if (! lastAttr) {
ljam();
return; /* EXIT AND WAIT FOR MORE */
}//if
......@@ -491,11 +519,11 @@ void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr)
void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
{
fragOperPtr.p->inUse = false;
fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
cfirstfreeFragopr = fragOperPtr.i;
}//Dbtup::releaseFragoperrec()
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
{
for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
......@@ -510,6 +538,20 @@ void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
ndbrequire(false);
}//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
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
......
......@@ -575,6 +575,7 @@ private:
void execDROP_TAB_REQ(Signal* signal);
bool allocDescEnt(IndexPtr indexPtr);
void freeDescEnt(IndexPtr indexPtr);
void abortAddFragOp(Signal* signal);
void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
/*
......@@ -684,6 +685,7 @@ private:
friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
friend class NdbOut& operator<<(NdbOut&, const Index&);
friend class NdbOut& operator<<(NdbOut&, const Frag&);
friend class NdbOut& operator<<(NdbOut&, const FragOp&);
friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
FILE* debugFile;
NdbOut debugOut;
......
......@@ -403,6 +403,19 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
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&
operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
{
......
......@@ -24,12 +24,7 @@ Dbtux::Dbtux(const Configuration& conf) :
#ifdef VM_TRACE
debugFile(0),
debugOut(*new NullOutputStream()),
// until ndb_mgm supports dump
#ifdef DBTUX_DEBUG_TREE
debugFlags(DebugTree),
#else
debugFlags(0),
#endif
#endif
c_internalStartPhase(0),
c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
......@@ -86,7 +81,7 @@ Dbtux::execCONTINUEB(Signal* signal)
jamEntry();
const Uint32* data = signal->getDataPtr();
switch (data[0]) {
case TuxContinueB::DropIndex:
case TuxContinueB::DropIndex: // currently unused
{
IndexPtr indexPtr;
c_indexPool.getPtr(indexPtr, data[1]);
......@@ -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_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;
c_indexPool.setSize(nIndex);
......
......@@ -29,6 +29,11 @@ void
Dbtux::execTUXFRAGREQ(Signal* signal)
{
jamEntry();
if (signal->theData[0] == (Uint32)-1) {
jam();
abortAddFragOp(signal);
return;
}
const TuxFragReq reqCopy = *(const TuxFragReq*)signal->getDataPtr();
const TuxFragReq* const req = &reqCopy;
IndexPtr indexPtr;
......@@ -61,6 +66,11 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragOpPtr.p->m_fragId = req->fragId;
fragOpPtr.p->m_fragNo = indexPtr.p->m_numFrags;
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
ndbrequire(indexPtr.p->m_numFrags < MaxIndexFragments);
// seize new fragment record
......@@ -129,6 +139,14 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
debugOut << "Add frag " << fragPtr.i << " " << *fragPtr.p << endl;
}
#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
TuxFragConf* const conf = (TuxFragConf*)signal->getDataPtrSend();
conf->userPtr = req->userPtr;
......@@ -145,10 +163,18 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
ref->errorCode = errorCode;
sendSignal(req->userRef, GSN_TUXFRAGREF,
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);
if (indexPtr.i != RNIL)
dropIndex(signal, indexPtr, 0, 0);
}
if (indexPtr.i != RNIL) {
jam();
// let DICT drop the unfinished index
}
}
void
......@@ -203,7 +229,16 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
}
}
#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();
// initialize tree header
TreeHead& tree = fragPtr.p->m_tree;
......@@ -246,11 +281,17 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
}
#endif
// fragment is defined
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Release frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
}
#endif
c_fragOpPool.release(fragOpPtr);
}
// success
TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend();
conf->userPtr = fragOpPtr.p->m_userPtr;
conf->lastAttr = lastAttr;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB);
return;
......@@ -261,8 +302,32 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
ref->errorCode = errorCode;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF,
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);
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
{
jam();
indexPtr.p->m_state = Index::Dropping;
// drop one fragment at a time
if (indexPtr.p->m_numFrags > 0) {
// drop fragments
while (indexPtr.p->m_numFrags > 0) {
jam();
unsigned i = --indexPtr.p->m_numFrags;
Uint32 i = --indexPtr.p->m_numFrags;
FragPtr fragPtr;
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
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
if (indexPtr.p->m_descPage != RNIL) {
......
......@@ -1479,6 +1479,69 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
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);
TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){
......@@ -1574,6 +1637,10 @@ TESTCASE("DictionaryPerf",
""){
INITIALIZER(runTestDictionaryPerf);
}
TESTCASE("FailAddFragment",
"Fail add fragment or attribute in TUP or TUX\n"){
INITIALIZER(runFailAddFragment);
}
NDBT_TESTSUITE_END(testDict);
int main(int argc, const char** argv){
......
......@@ -2144,22 +2144,19 @@ void ha_ndbcluster::print_results()
}
case NdbDictionary::Column::Decimal: {
char *value= field->ptr;
fprintf(DBUG_FILE, "Decimal\t'%-*s'", field->pack_length(), value);
break;
}
case NdbDictionary::Column::Char:{
char buf[field->pack_length()+1];
char *value= (char *) field->ptr;
snprintf(buf, field->pack_length(), "%s", value);
fprintf(DBUG_FILE, "Char\t'%s'", buf);
const char *value= (char *) field->ptr;
fprintf(DBUG_FILE, "Char\t'%.*s'", field->pack_length(), value);
break;
}
case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Varbinary: {
char *value= (char *) field->ptr;
fprintf(DBUG_FILE, "'%s'", value);
const char *value= (char *) field->ptr;
fprintf(DBUG_FILE, "Var\t'%.*s'", field->pack_length(), value);
break;
}
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