ndb - bug#18781 bug#21017 bug#21050 : block index ops during NR + fix asserts

parent 64092ca9
...@@ -192,6 +192,7 @@ public: ...@@ -192,6 +192,7 @@ public:
enum ErrorCode { enum ErrorCode {
NoError = 0, NoError = 0,
Busy = 701, Busy = 701,
BusyWithNR = 711,
NotMaster = 702, NotMaster = 702,
TriggerNotFound = 4238, TriggerNotFound = 4238,
TriggerExists = 4239, TriggerExists = 4239,
......
...@@ -168,6 +168,7 @@ public: ...@@ -168,6 +168,7 @@ public:
NoError = 0, NoError = 0,
InvalidIndexVersion = 241, InvalidIndexVersion = 241,
Busy = 701, Busy = 701,
BusyWithNR = 711,
NotMaster = 702, NotMaster = 702,
IndexNotFound = 4243, IndexNotFound = 4243,
BadRequestType = 4247, BadRequestType = 4247,
......
...@@ -6520,9 +6520,18 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal) ...@@ -6520,9 +6520,18 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal)
} }
if (signal->getLength() == CreateIndxReq::SignalLength) { if (signal->getLength() == CreateIndxReq::SignalLength) {
jam(); jam();
CreateIndxRef::ErrorCode tmperr = CreateIndxRef::NoError;
if (getOwnNodeId() != c_masterNodeId) { if (getOwnNodeId() != c_masterNodeId) {
jam(); jam();
tmperr = CreateIndxRef::NotMaster;
} else if (c_blockState == BS_NODE_RESTART) {
jam();
tmperr = CreateIndxRef::BusyWithNR;
} else if (c_blockState != BS_IDLE) {
jam();
tmperr = CreateIndxRef::Busy;
}
if (tmperr != CreateIndxRef::NoError) {
releaseSections(signal); releaseSections(signal);
OpCreateIndex opBusy; OpCreateIndex opBusy;
opPtr.p = &opBusy; opPtr.p = &opBusy;
...@@ -6530,13 +6539,12 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal) ...@@ -6530,13 +6539,12 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal)
opPtr.p->m_isMaster = (senderRef == reference()); opPtr.p->m_isMaster = (senderRef == reference());
opPtr.p->key = 0; opPtr.p->key = 0;
opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE; opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
opPtr.p->m_errorCode = CreateIndxRef::NotMaster; opPtr.p->m_errorCode = tmperr;
opPtr.p->m_errorLine = __LINE__; opPtr.p->m_errorLine = __LINE__;
opPtr.p->m_errorNode = c_masterNodeId; opPtr.p->m_errorNode = c_masterNodeId;
createIndex_sendReply(signal, opPtr, true); createIndex_sendReply(signal, opPtr, true);
return; return;
} }
// forward initial request plus operation key to all // forward initial request plus operation key to all
req->setOpKey(++c_opRecordSequence); req->setOpKey(++c_opRecordSequence);
NodeReceiverGroup rg(DBDICT, c_aliveNodes); NodeReceiverGroup rg(DBDICT, c_aliveNodes);
...@@ -7082,10 +7090,19 @@ Dbdict::execDROP_INDX_REQ(Signal* signal) ...@@ -7082,10 +7090,19 @@ Dbdict::execDROP_INDX_REQ(Signal* signal)
jam(); jam();
if (signal->getLength() == DropIndxReq::SignalLength) { if (signal->getLength() == DropIndxReq::SignalLength) {
jam(); jam();
DropIndxRef::ErrorCode tmperr = DropIndxRef::NoError;
if (getOwnNodeId() != c_masterNodeId) { if (getOwnNodeId() != c_masterNodeId) {
jam(); jam();
tmperr = DropIndxRef::NotMaster;
err = DropIndxRef::NotMaster; } else if (c_blockState == BS_NODE_RESTART) {
jam();
tmperr = DropIndxRef::BusyWithNR;
} else if (c_blockState != BS_IDLE) {
jam();
tmperr = DropIndxRef::Busy;
}
if (tmperr != DropIndxRef::NoError) {
err = tmperr;
goto error; goto error;
} }
// forward initial request plus operation key to all // forward initial request plus operation key to all
...@@ -10130,6 +10147,17 @@ Dbdict::execDICT_LOCK_REQ(Signal* signal) ...@@ -10130,6 +10147,17 @@ Dbdict::execDICT_LOCK_REQ(Signal* signal)
sendDictLockInfoEvent(lockPtr, "lock request by node"); sendDictLockInfoEvent(lockPtr, "lock request by node");
} }
// only table and index ops are checked
bool
Dbdict::hasDictLockSchemaOp()
{
return
! c_opCreateTable.isEmpty() ||
! c_opDropTable.isEmpty() ||
! c_opCreateIndex.isEmpty() ||
! c_opDropIndex.isEmpty();
}
void void
Dbdict::checkDictLockQueue(Signal* signal, bool poll) Dbdict::checkDictLockQueue(Signal* signal, bool poll)
{ {
...@@ -10150,7 +10178,7 @@ Dbdict::checkDictLockQueue(Signal* signal, bool poll) ...@@ -10150,7 +10178,7 @@ Dbdict::checkDictLockQueue(Signal* signal, bool poll)
break; break;
} }
if (c_opRecordPool.getNoOfFree() != c_opRecordPool.getSize()) { if (hasDictLockSchemaOp()) {
jam(); jam();
break; break;
} }
...@@ -10183,7 +10211,7 @@ Dbdict::execDICT_UNLOCK_ORD(Signal* signal) ...@@ -10183,7 +10211,7 @@ Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
if (lockPtr.p->locked) { if (lockPtr.p->locked) {
jam(); jam();
ndbrequire(c_blockState == lockPtr.p->lt->blockState); ndbrequire(c_blockState == lockPtr.p->lt->blockState);
ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize()); ndbrequire(! hasDictLockSchemaOp());
ndbrequire(! c_dictLockQueue.hasPrev(lockPtr)); ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
c_blockState = BS_IDLE; c_blockState = BS_IDLE;
...@@ -10279,7 +10307,7 @@ Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes) ...@@ -10279,7 +10307,7 @@ Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
if (lockPtr.p->locked) { if (lockPtr.p->locked) {
jam(); jam();
ndbrequire(c_blockState == lockPtr.p->lt->blockState); ndbrequire(c_blockState == lockPtr.p->lt->blockState);
ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize()); ndbrequire(! hasDictLockSchemaOp());
ndbrequire(! c_dictLockQueue.hasPrev(lockPtr)); ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
c_blockState = BS_IDLE; c_blockState = BS_IDLE;
......
...@@ -1650,6 +1650,9 @@ private: ...@@ -1650,6 +1650,9 @@ private:
void sendDictLockInfoEvent(Uint32 pollCount); void sendDictLockInfoEvent(Uint32 pollCount);
void sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text); void sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text);
// check if any schema op exists (conflicting with dict lock)
bool hasDictLockSchemaOp();
void checkDictLockQueue(Signal* signal, bool poll); void checkDictLockQueue(Signal* signal, bool poll);
void sendDictLockConf(Signal* signal, DictLockPtr lockPtr); void sendDictLockConf(Signal* signal, DictLockPtr lockPtr);
void sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode); void sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode);
......
...@@ -147,6 +147,8 @@ public: ...@@ -147,6 +147,8 @@ public:
* @param iter - An "uninitialized" iterator * @param iter - An "uninitialized" iterator
*/ */
bool next(Uint32 bucket, Iterator & iter) const; bool next(Uint32 bucket, Iterator & iter) const;
inline bool isEmpty() const { Iterator iter; return ! first(iter); }
private: private:
Uint32 mask; Uint32 mask;
......
...@@ -42,6 +42,8 @@ public: ...@@ -42,6 +42,8 @@ public:
static const NdbDictionary::Table* getTable(int _num); static const NdbDictionary::Table* getTable(int _num);
static int getNumTables(); static int getNumTables();
static const char** getIndexes(const char* table);
private: private:
static const NdbDictionary::Table* tableWithPkSize(const char* _nam, Uint32 pkSize); static const NdbDictionary::Table* tableWithPkSize(const char* _nam, Uint32 pkSize);
}; };
......
...@@ -1022,8 +1022,8 @@ int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary:: ...@@ -1022,8 +1022,8 @@ int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::
if (!pTab->equal(*pTab2)){ if (!pTab->equal(*pTab2)){
g_err << "equal failed" << endl; g_err << "equal failed" << endl;
g_info << *pTab; g_info << *(NDBT_Table*)pTab; // gcc-4.1.2
g_info << *pTab2; g_info << *(NDBT_Table*)pTab2;
return NDBT_FAILED; return NDBT_FAILED;
} }
return NDBT_OK; return NDBT_OK;
...@@ -1033,7 +1033,7 @@ int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -1033,7 +1033,7 @@ int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step); Ndb* pNdb = GETNDB(step);
const NdbDictionary::Table* pTab = ctx->getTab(); const NdbDictionary::Table* pTab = ctx->getTab();
ndbout << "|- " << pTab->getName() << endl; ndbout << "|- " << pTab->getName() << endl;
g_info << *pTab; g_info << *(NDBT_Table*)pTab;
// Try to create table in db // Try to create table in db
if (pTab->createTableInDb(pNdb) != 0){ if (pTab->createTableInDb(pNdb) != 0){
return NDBT_FAILED; return NDBT_FAILED;
...@@ -1890,6 +1890,52 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) ...@@ -1890,6 +1890,52 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step)
// replace by the Retrieved table // replace by the Retrieved table
pTab = pTab2; pTab = pTab2;
// create indexes
const char** indlist = NDBT_Tables::getIndexes(tabName);
uint indnum = 0;
while (*indlist != 0) {
uint count = 0;
try_create_index:
count++;
if (count == 1)
g_info << "2: create index " << indnum << " " << *indlist << endl;
NdbDictionary::Index ind;
char indName[200];
sprintf(indName, "%s_X%u", tabName, indnum);
ind.setName(indName);
ind.setTable(tabName);
if (strcmp(*indlist, "UNIQUE") == 0) {
ind.setType(NdbDictionary::Index::UniqueHashIndex);
ind.setLogging(pTab->getLogging());
} else if (strcmp(*indlist, "ORDERED") == 0) {
ind.setType(NdbDictionary::Index::OrderedIndex);
ind.setLogging(false);
} else {
assert(false);
}
const char** indtemp = indlist;
while (*++indtemp != 0) {
ind.addColumn(*indtemp);
}
if (pDic->createIndex(ind) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << indName << ": create failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_create_index;
}
indlist = ++indtemp;
indnum++;
}
if (result == NDBT_FAILED)
break;
uint indcount = indnum;
int records = myRandom48(ctx->getNumRecords()); int records = myRandom48(ctx->getNumRecords());
g_info << "2: load " << records << " records" << endl; g_info << "2: load " << records << " records" << endl;
HugoTransactions hugoTrans(*pTab); HugoTransactions hugoTrans(*pTab);
...@@ -1901,6 +1947,32 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) ...@@ -1901,6 +1947,32 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step)
} }
NdbSleep_MilliSleep(myRandom48(maxsleep)); NdbSleep_MilliSleep(myRandom48(maxsleep));
// drop indexes
indnum = 0;
while (indnum < indcount) {
uint count = 0;
try_drop_index:
count++;
if (count == 1)
g_info << "2: drop index " << indnum << endl;
char indName[200];
sprintf(indName, "%s_X%u", tabName, indnum);
if (pDic->dropIndex(indName, tabName) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << indName << ": drop failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_drop_index;
}
indnum++;
}
if (result == NDBT_FAILED)
break;
g_info << "2: drop" << endl; g_info << "2: drop" << endl;
{ {
uint count = 0; uint count = 0;
......
...@@ -799,6 +799,17 @@ NDBT_Tables::getNumTables(){ ...@@ -799,6 +799,17 @@ NDBT_Tables::getNumTables(){
return numTestTables; return numTestTables;
} }
const char**
NDBT_Tables::getIndexes(const char* table)
{
Uint32 i = 0;
for (i = 0; indexes[i].m_table != 0; i++) {
if (strcmp(indexes[i].m_table, table) == 0)
return indexes[i].m_indexes;
}
return 0;
}
int int
NDBT_Tables::createAllTables(Ndb* pNdb, bool _temp, bool existsOk){ NDBT_Tables::createAllTables(Ndb* pNdb, bool _temp, bool existsOk){
......
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