diff options
Diffstat (limited to 'ndb')
25 files changed, 812 insertions, 346 deletions
diff --git a/ndb/include/kernel/signaldata/AlterTable.hpp b/ndb/include/kernel/signaldata/AlterTable.hpp index 30f8727551d..173a9acf9ed 100644 --- a/ndb/include/kernel/signaldata/AlterTable.hpp +++ b/ndb/include/kernel/signaldata/AlterTable.hpp @@ -128,7 +128,8 @@ public: RecordTooBig = 738, InvalidPrimaryKeySize = 739, NullablePrimaryKey = 740, - UnsupportedChange = 741 + UnsupportedChange = 741, + BackupInProgress = 762 }; private: diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp index 09b00cf8993..bc4817f0cf3 100644 --- a/ndb/include/kernel/signaldata/DictTabInfo.hpp +++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp @@ -215,6 +215,7 @@ public: StateBuilding = 2, StateDropping = 3, StateOnline = 4, + StateBackup = 5, StateBroken = 9 }; diff --git a/ndb/include/kernel/signaldata/DropTable.hpp b/ndb/include/kernel/signaldata/DropTable.hpp index 7a5b96e4cd1..cae6aff8754 100644 --- a/ndb/include/kernel/signaldata/DropTable.hpp +++ b/ndb/include/kernel/signaldata/DropTable.hpp @@ -57,7 +57,8 @@ public: NoSuchTable = 709, InvalidTableVersion = 241, DropInProgress = 283, - NoDropTableRecordAvailable = 1229 + NoDropTableRecordAvailable = 1229, + BackupInProgress = 761 }; }; diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index 86130be4c4b..6ae8aa16977 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -117,6 +117,7 @@ public: StateBuilding = 2, ///< Building, not yet usable StateDropping = 3, ///< Offlining or dropping, not usable StateOnline = 4, ///< Online, usable + StateBackup = 5, ///< Online, being backuped, usable StateBroken = 9 ///< Broken, should be dropped and re-created }; diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 327fcc33aff..ecc329c641b 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -921,7 +921,6 @@ Backup::execUTIL_SEQUENCE_REF(Signal* signal) jamEntry(); UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr(); ptr.i = utilRef->senderData; - ndbrequire(ptr.i == RNIL); c_backupPool.getPtr(ptr); ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ); sendBackupRef(signal, ptr, BackupRef::SequenceFailure); @@ -2418,10 +2417,16 @@ Backup::execLIST_TABLES_CONF(Signal* signal) jam(); Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]); Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]); + Uint32 state= ListTablesConf::getTableState(conf->tableData[i]); if (!DictTabInfo::isTable(tableType) && !DictTabInfo::isIndex(tableType)){ jam(); continue; }//if + if (state != DictTabInfo::StateOnline) + { + jam(); + continue; + }//if TablePtr tabPtr; ptr.p->tables.seize(tabPtr); if(tabPtr.i == RNIL) { @@ -2791,10 +2796,19 @@ Backup::execGET_TABINFO_CONF(Signal* signal) TablePtr tmp = tabPtr; ptr.p->tables.next(tabPtr); - if(DictTabInfo::isIndex(tmp.p->tableType)){ + if(DictTabInfo::isIndex(tmp.p->tableType)) + { + jam(); ptr.p->tables.release(tmp); } - + else + { + jam(); + signal->theData[0] = tmp.p->tableId; + signal->theData[1] = 1; // lock + EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2); + } + if(tabPtr.i == RNIL) { jam(); @@ -3575,7 +3589,7 @@ Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr) ref->backupId = ptr.p->backupId; ref->backupPtr = ptr.i; ref->nodeId = getOwnNodeId(); - ref->errorCode = ptr.p->errorCode; + ref->errorCode = filePtr.p->errorCode; sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal, BackupFragmentRef::SignalLength, JBB); } @@ -3836,6 +3850,8 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize)) { jam(); + Uint32 save[TrigAttrInfo::StaticLength]; + memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength); BackupRecordPtr ptr; c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull; @@ -3846,6 +3862,8 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { ord->senderData= ptr.i; sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, AbortBackupOrd::SignalLength, JBB); + + memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength); return; }//if @@ -3995,6 +4013,17 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) gcp->StopGCP = htonl(stopGCP - 1); filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz); } + + { + TablePtr tabPtr; + for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL; + ptr.p->tables.next(tabPtr)) + { + signal->theData[0] = tabPtr.p->tableId; + signal->theData[1] = 0; // unlock + EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2); + } + } closeFiles(signal, ptr); } @@ -4338,6 +4367,11 @@ Backup::cleanup(Signal* signal, BackupRecordPtr ptr) }//if tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID; }//for + { + signal->theData[0] = tabPtr.p->tableId; + signal->theData[1] = 0; // unlock + EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2); + } }//for BackupFilePtr filePtr; @@ -4354,9 +4388,6 @@ Backup::cleanup(Signal* signal, BackupRecordPtr ptr) ptr.p->files.release(); ptr.p->tables.release(); ptr.p->triggers.release(); - - ptr.p->tables.release(); - ptr.p->triggers.release(); ptr.p->pages.release(); ptr.p->backupId = ~0; diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 24f9715c8b4..1a64b8f9e1e 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -4845,7 +4845,24 @@ Uint32 Dbacc::executeNextOperation(Signal* signal) sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal, 2, JBB); return operationRecPtr.p->elementIsDisappeared; }//if - }//if + } + else if(operationRecPtr.p->operation == ZWRITE) + { + jam(); + operationRecPtr.p->operation = ZINSERT; + if (operationRecPtr.p->prevParallelQue != RNIL) { + OperationrecPtr prevOpPtr; + jam(); + prevOpPtr.i = operationRecPtr.p->prevParallelQue; + ptrCheckGuard(prevOpPtr, coprecsize, operationrec); + if (prevOpPtr.p->operation != ZDELETE) + { + jam(); + operationRecPtr.p->operation = ZUPDATE; + } + } + } + if (operationRecPtr.p->operation == ZSCAN_OP && ! operationRecPtr.p->isAccLockReq) { jam(); diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index d51f9537154..a9114540940 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -1331,6 +1331,8 @@ Dbdict::Dbdict(const class Configuration & conf): addRecSignal(GSN_DROP_TAB_REQ, &Dbdict::execDROP_TAB_REQ); addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF); addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF); + + addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ); }//Dbdict::Dbdict() Dbdict::~Dbdict() @@ -1486,7 +1488,6 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr) tablePtr.p->tableVersion = (Uint32)-1; tablePtr.p->tabState = TableRecord::NOT_DEFINED; tablePtr.p->tabReturnState = TableRecord::TRS_IDLE; - tablePtr.p->myConnect = RNIL; tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable; memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName)); tablePtr.p->gciTableCreated = 0; @@ -2961,6 +2962,27 @@ Dbdict::execCREATE_TABLE_REQ(Signal* signal){ } void +Dbdict::execBACKUP_FRAGMENT_REQ(Signal* signal) +{ + jamEntry(); + Uint32 tableId = signal->theData[0]; + Uint32 lock = signal->theData[1]; + + TableRecordPtr tablePtr; + c_tableRecordPool.getPtr(tablePtr, tableId, true); + + if(lock) + { + ndbrequire(tablePtr.p->tabState == TableRecord::DEFINED); + tablePtr.p->tabState = TableRecord::BACKUP_ONGOING; + } + else if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) + { + tablePtr.p->tabState = TableRecord::DEFINED; + } +} + +void Dbdict::execALTER_TABLE_REQ(Signal* signal) { // Received by master @@ -3011,6 +3033,10 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) ok = true; jam(); break; + case TableRecord::BACKUP_ONGOING: + jam(); + alterTableRef(signal, req, AlterTableRef::BackupInProgress); + return; case TableRecord::PREPARE_DROPPING: case TableRecord::DROPPING: jam(); @@ -3030,7 +3056,6 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) CreateTableRecordPtr alterTabPtr; // Reuse create table records c_opCreateTable.seize(alterTabPtr); - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; if(alterTabPtr.isNull()){ jam(); @@ -3038,7 +3063,7 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) return; } - regAlterTabPtr->m_changeMask = changeMask; + alterTabPtr.p->m_changeMask = changeMask; parseRecord.requestType = DictTabInfo::AlterTableFromAPI; parseRecord.errorCode = 0; @@ -3058,20 +3083,17 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) } releaseSections(signal); - regAlterTabPtr->key = ++c_opRecordSequence; + alterTabPtr.p->key = ++c_opRecordSequence; c_opCreateTable.add(alterTabPtr); - ndbrequire(c_opCreateTable.find(alterTabPtr, regAlterTabPtr->key)); - regAlterTabPtr->m_errorCode = 0; - regAlterTabPtr->m_senderRef = senderRef; - regAlterTabPtr->m_senderData = senderData; - regAlterTabPtr->m_tablePtrI = parseRecord.tablePtr.i; - regAlterTabPtr->m_alterTableFailed = false; - regAlterTabPtr->m_coordinatorRef = reference(); - regAlterTabPtr->m_fragmentsPtrI = RNIL; - regAlterTabPtr->m_dihAddFragPtr = RNIL; - - // Alter table on all nodes - c_blockState = BS_BUSY; + ndbrequire(c_opCreateTable.find(alterTabPtr, alterTabPtr.p->key)); + alterTabPtr.p->m_errorCode = 0; + alterTabPtr.p->m_senderRef = senderRef; + alterTabPtr.p->m_senderData = senderData; + alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i; + alterTabPtr.p->m_alterTableFailed = false; + alterTabPtr.p->m_coordinatorRef = reference(); + alterTabPtr.p->m_fragmentsPtrI = RNIL; + alterTabPtr.p->m_dihAddFragPtr = RNIL; // Send prepare request to all alive nodes SimplePropertiesSectionWriter w(getSectionSegmentPool()); @@ -3079,27 +3101,74 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) SegmentedSectionPtr tabInfoPtr; w.getPtr(tabInfoPtr); + + alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i; + + // Alter table on all nodes + c_blockState = BS_BUSY; + + Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex); + Callback c = { safe_cast(&Dbdict::alterTable_backup_mutex_locked), + alterTabPtr.p->key }; + + ndbrequire(mutex.lock(c)); +} + +void +Dbdict::alterTable_backup_mutex_locked(Signal* signal, + Uint32 callbackData, + Uint32 retValue) +{ + jamEntry(); + + ndbrequire(retValue == 0); + + CreateTableRecordPtr alterTabPtr; + ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData)); + + TableRecordPtr tablePtr; + c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_tablePtrI, true); + + Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex); + mutex.unlock(); // ignore response + + SegmentedSectionPtr tabInfoPtr; + getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI); signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO); + alterTabPtr.p->m_tabInfoPtrI = RNIL; + + if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) + { + jam(); + AlterTableReq* req = (AlterTableReq*)signal->getDataPtr(); + req->senderData = alterTabPtr.p->m_senderData; + req->senderRef = alterTabPtr.p->m_senderRef; + alterTableRef(signal, req, AlterTableRef::BackupInProgress); + c_opCreateTable.release(alterTabPtr); + c_blockState = BS_IDLE; + return; + } + NodeReceiverGroup rg(DBDICT, c_aliveNodes); - regAlterTabPtr->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; - SafeCounter safeCounter(c_counterMgr, regAlterTabPtr->m_coordinatorData.m_counter); - safeCounter.init<AlterTabRef>(rg, regAlterTabPtr->key); + alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; + SafeCounter safeCounter(c_counterMgr, + alterTabPtr.p->m_coordinatorData.m_counter); + safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key); AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend(); lreq->senderRef = reference(); - lreq->senderData = regAlterTabPtr->key; - lreq->clientRef = regAlterTabPtr->m_senderRef; - lreq->clientData = regAlterTabPtr->m_senderData; - lreq->changeMask = changeMask; - lreq->tableId = tableId; - lreq->tableVersion = tableVersion + 1; + lreq->senderData = alterTabPtr.p->key; + lreq->clientRef = alterTabPtr.p->m_senderRef; + lreq->clientData = alterTabPtr.p->m_senderData; + lreq->changeMask = alterTabPtr.p->m_changeMask; + lreq->tableId = tablePtr.p->tableId; + lreq->tableVersion = tablePtr.p->tableVersion + 1; lreq->gci = tablePtr.p->gciTableCreated; lreq->requestType = AlterTabReq::AlterTablePrepare; sendSignal(rg, GSN_ALTER_TAB_REQ, signal, AlterTabReq::SignalLength, JBB); - } void Dbdict::alterTableRef(Signal * signal, @@ -3174,9 +3243,8 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) alterTabRef(signal, req, AlterTableRef::Busy); return; } - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; - regAlterTabPtr->m_alterTableId = tableId; - regAlterTabPtr->m_coordinatorRef = senderRef; + alterTabPtr.p->m_alterTableId = tableId; + alterTabPtr.p->m_coordinatorRef = senderRef; // Get table definition TableRecordPtr tablePtr; @@ -3210,6 +3278,10 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) jam(); alterTabRef(signal, req, AlterTableRef::DropInProgress); return; + case TableRecord::BACKUP_ONGOING: + jam(); + alterTabRef(signal, req, AlterTableRef::BackupInProgress); + return; } ndbrequire(ok); @@ -3240,23 +3312,23 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) aParseRecord); return; } - regAlterTabPtr->key = senderData; + alterTabPtr.p->key = senderData; c_opCreateTable.add(alterTabPtr); - regAlterTabPtr->m_errorCode = 0; - regAlterTabPtr->m_senderRef = senderRef; - regAlterTabPtr->m_senderData = senderData; - regAlterTabPtr->m_tablePtrI = parseRecord.tablePtr.i; - regAlterTabPtr->m_fragmentsPtrI = RNIL; - regAlterTabPtr->m_dihAddFragPtr = RNIL; + alterTabPtr.p->m_errorCode = 0; + alterTabPtr.p->m_senderRef = senderRef; + alterTabPtr.p->m_senderData = senderData; + alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i; + alterTabPtr.p->m_fragmentsPtrI = RNIL; + alterTabPtr.p->m_dihAddFragPtr = RNIL; newTablePtr = parseRecord.tablePtr; newTablePtr.p->tableVersion = tableVersion; } else { // (req->senderRef == reference()) jam(); - c_tableRecordPool.getPtr(newTablePtr, regAlterTabPtr->m_tablePtrI); + c_tableRecordPool.getPtr(newTablePtr, alterTabPtr.p->m_tablePtrI); newTablePtr.p->tableVersion = tableVersion; } - if (handleAlterTab(req, regAlterTabPtr, tablePtr, newTablePtr) == -1) { + if (handleAlterTab(req, alterTabPtr.p, tablePtr, newTablePtr) == -1) { jam(); c_opCreateTable.release(alterTabPtr); alterTabRef(signal, req, AlterTableRef::UnsupportedChange); @@ -3281,7 +3353,7 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) // Write schema for altered table to disk SegmentedSectionPtr tabInfoPtr; signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO); - regAlterTabPtr->m_tabInfoPtrI = tabInfoPtr.i; + alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i; signal->header.m_noOfSections = 0; @@ -3309,7 +3381,7 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) case(AlterTabReq::AlterTableRevert): { jam(); // Revert failed alter table - revertAlterTable(signal, changeMask, tableId, regAlterTabPtr); + revertAlterTable(signal, changeMask, tableId, alterTabPtr.p); // Acknowledge the reverted alter table AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend(); conf->senderRef = reference(); @@ -3373,9 +3445,8 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){ (AlterTabReq::RequestType) ref->requestType; CreateTableRecordPtr alterTabPtr; ndbrequire(c_opCreateTable.find(alterTabPtr, senderData)); - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; - Uint32 changeMask = regAlterTabPtr->m_changeMask; - SafeCounter safeCounter(c_counterMgr, regAlterTabPtr->m_coordinatorData.m_counter); + Uint32 changeMask = alterTabPtr.p->m_changeMask; + SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter); safeCounter.clearWaitingFor(refToNode(senderRef)); switch (requestType) { case(AlterTabReq::AlterTablePrepare): { @@ -3383,7 +3454,7 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){ jam(); // Send revert request to all alive nodes TableRecordPtr tablePtr; - c_tableRecordPool.getPtr(tablePtr, regAlterTabPtr->m_alterTableId); + c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId); Uint32 tableId = tablePtr.p->tableId; Uint32 tableVersion = tablePtr.p->tableVersion; Uint32 gci = tablePtr.p->gciTableCreated; @@ -3394,14 +3465,14 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){ signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO); NodeReceiverGroup rg(DBDICT, c_aliveNodes); - regAlterTabPtr->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; - safeCounter.init<AlterTabRef>(rg, regAlterTabPtr->key); + alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; + safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key); AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend(); lreq->senderRef = reference(); - lreq->senderData = regAlterTabPtr->key; - lreq->clientRef = regAlterTabPtr->m_senderRef; - lreq->clientData = regAlterTabPtr->m_senderData; + lreq->senderData = alterTabPtr.p->key; + lreq->clientRef = alterTabPtr.p->m_senderRef; + lreq->clientData = alterTabPtr.p->m_senderData; lreq->changeMask = changeMask; lreq->tableId = tableId; lreq->tableVersion = tableVersion; @@ -3413,7 +3484,7 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){ } else { jam(); - regAlterTabPtr->m_alterTableFailed = true; + alterTabPtr.p->m_alterTableFailed = true; } break; } @@ -3437,8 +3508,8 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){ } else { jam(); - regAlterTabPtr->m_alterTableFailed = true; - regAlterTabPtr->m_alterTableRef = *apiRef; + alterTabPtr.p->m_alterTableFailed = true; + alterTabPtr.p->m_alterTableRef = *apiRef; } break; } @@ -3460,7 +3531,6 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ (AlterTabReq::RequestType) conf->requestType; CreateTableRecordPtr alterTabPtr; ndbrequire(c_opCreateTable.find(alterTabPtr, senderData)); - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; switch (requestType) { case(AlterTabReq::AlterTablePrepare): { @@ -3504,23 +3574,23 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ conf->tableVersion = tableVersion; conf->gci = gci; conf->requestType = requestType; - sendSignal(regAlterTabPtr->m_coordinatorRef, GSN_ALTER_TAB_CONF, signal, + sendSignal(alterTabPtr.p->m_coordinatorRef, GSN_ALTER_TAB_CONF, signal, AlterTabConf::SignalLength, JBB); return; } default :break; } // Coordinator only - SafeCounter safeCounter(c_counterMgr, regAlterTabPtr->m_coordinatorData.m_counter); + SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter); safeCounter.clearWaitingFor(refToNode(senderRef)); if (safeCounter.done()) { jam(); // We have received all local confirmations - if (regAlterTabPtr->m_alterTableFailed) { + if (alterTabPtr.p->m_alterTableFailed) { jam(); // Send revert request to all alive nodes TableRecordPtr tablePtr; - c_tableRecordPool.getPtr(tablePtr, regAlterTabPtr->m_alterTableId); + c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId); Uint32 tableId = tablePtr.p->tableId; Uint32 tableVersion = tablePtr.p->tableVersion; Uint32 gci = tablePtr.p->gciTableCreated; @@ -3531,14 +3601,14 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO); NodeReceiverGroup rg(DBDICT, c_aliveNodes); - regAlterTabPtr->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; - safeCounter.init<AlterTabRef>(rg, regAlterTabPtr->key); + alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; + safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key); AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend(); lreq->senderRef = reference(); - lreq->senderData = regAlterTabPtr->key; - lreq->clientRef = regAlterTabPtr->m_senderRef; - lreq->clientData = regAlterTabPtr->m_senderData; + lreq->senderData = alterTabPtr.p->key; + lreq->clientRef = alterTabPtr.p->m_senderRef; + lreq->clientData = alterTabPtr.p->m_senderData; lreq->changeMask = changeMask; lreq->tableId = tableId; lreq->tableVersion = tableVersion; @@ -3560,14 +3630,14 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO); NodeReceiverGroup rg(DBDICT, c_aliveNodes); - regAlterTabPtr->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; - safeCounter.init<AlterTabRef>(rg, regAlterTabPtr->key); + alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ; + safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key); AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend(); lreq->senderRef = reference(); - lreq->senderData = regAlterTabPtr->key; - lreq->clientRef = regAlterTabPtr->m_senderRef; - lreq->clientData = regAlterTabPtr->m_senderData; + lreq->senderData = alterTabPtr.p->key; + lreq->clientRef = alterTabPtr.p->m_senderRef; + lreq->clientData = alterTabPtr.p->m_senderData; lreq->changeMask = changeMask; lreq->tableId = tableId; lreq->tableVersion = tableVersion; @@ -3587,18 +3657,18 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ case(AlterTabReq::AlterTableRevert): jam(); case(AlterTabReq::AlterTableCommit): { - SafeCounter safeCounter(c_counterMgr, regAlterTabPtr->m_coordinatorData.m_counter); + SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter); safeCounter.clearWaitingFor(refToNode(senderRef)); if (safeCounter.done()) { jam(); // We have received all local confirmations releaseSections(signal); - if (regAlterTabPtr->m_alterTableFailed) { + if (alterTabPtr.p->m_alterTableFailed) { jam(); AlterTableRef * apiRef = (AlterTableRef*)signal->getDataPtrSend(); - *apiRef = regAlterTabPtr->m_alterTableRef; - sendSignal(regAlterTabPtr->m_senderRef, GSN_ALTER_TABLE_REF, signal, + *apiRef = alterTabPtr.p->m_alterTableRef; + sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_REF, signal, AlterTableRef::SignalLength, JBB); } else { @@ -3607,18 +3677,18 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ AlterTableConf * const apiConf = (AlterTableConf*)signal->getDataPtrSend(); apiConf->senderRef = reference(); - apiConf->senderData = regAlterTabPtr->m_senderData; + apiConf->senderData = alterTabPtr.p->m_senderData; apiConf->tableId = tableId; apiConf->tableVersion = tableVersion; //@todo check api failed - sendSignal(regAlterTabPtr->m_senderRef, GSN_ALTER_TABLE_CONF, signal, + sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_CONF, signal, AlterTableConf::SignalLength, JBB); } // Release resources TableRecordPtr tabPtr; - c_tableRecordPool.getPtr(tabPtr, regAlterTabPtr->m_tablePtrI); + c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI); releaseTableObject(tabPtr.i, false); c_opCreateTable.release(alterTabPtr); c_blockState = BS_IDLE; @@ -3649,7 +3719,7 @@ void Dbdict::printTables() } int Dbdict::handleAlterTab(AlterTabReq * req, - CreateTableRecord * regAlterTabPtr, + CreateTableRecord * alterTabPtrP, TableRecordPtr origTablePtr, TableRecordPtr newTablePtr) { @@ -3664,7 +3734,7 @@ int Dbdict::handleAlterTab(AlterTabReq * req, ndbrequire(c_tableRecordHash.find(tmp, *origTablePtr.p)); #endif c_tableRecordHash.remove(origTablePtr); - strcpy(regAlterTabPtr->previousTableName, origTablePtr.p->tableName); + strcpy(alterTabPtrP->previousTableName, origTablePtr.p->tableName); strcpy(origTablePtr.p->tableName, newTablePtr.p->tableName); // Set new schema version origTablePtr.p->tableVersion = newTablePtr.p->tableVersion; @@ -3683,7 +3753,7 @@ int Dbdict::handleAlterTab(AlterTabReq * req, void Dbdict::revertAlterTable(Signal * signal, Uint32 changeMask, Uint32 tableId, - CreateTableRecord * regAlterTabPtr) + CreateTableRecord * alterTabPtrP) { if (AlterTableReq::getNameFlag(changeMask)) { jam(); @@ -3698,7 +3768,7 @@ void Dbdict::revertAlterTable(Signal * signal, #endif c_tableRecordHash.remove(tablePtr); // Restore name - strcpy(tablePtr.p->tableName, regAlterTabPtr->previousTableName); + strcpy(tablePtr.p->tableName, alterTabPtrP->previousTableName); // Revert schema version tablePtr.p->tableVersion = tablePtr.p->tableVersion - 1; // Put it back @@ -3722,16 +3792,15 @@ Dbdict::alterTab_writeSchemaConf(Signal* signal, Uint32 key = callbackData; CreateTableRecordPtr alterTabPtr; ndbrequire(c_opCreateTable.find(alterTabPtr, key)); - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; - Uint32 tableId = regAlterTabPtr->m_alterTableId; + Uint32 tableId = alterTabPtr.p->m_alterTableId; Callback callback; - callback.m_callbackData = regAlterTabPtr->key; + callback.m_callbackData = alterTabPtr.p->key; callback.m_callbackFunction = safe_cast(&Dbdict::alterTab_writeTableConf); SegmentedSectionPtr tabInfoPtr; - getSection(tabInfoPtr, regAlterTabPtr->m_tabInfoPtrI); + getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI); writeTableFile(signal, tableId, tabInfoPtr, &callback); @@ -3747,10 +3816,9 @@ Dbdict::alterTab_writeTableConf(Signal* signal, jam(); CreateTableRecordPtr alterTabPtr; ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData)); - CreateTableRecord * regAlterTabPtr = alterTabPtr.p; - Uint32 coordinatorRef = regAlterTabPtr->m_coordinatorRef; + Uint32 coordinatorRef = alterTabPtr.p->m_coordinatorRef; TableRecordPtr tabPtr; - c_tableRecordPool.getPtr(tabPtr, regAlterTabPtr->m_alterTableId); + c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_alterTableId); // Alter table commit request handled successfully AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend(); @@ -3765,7 +3833,7 @@ Dbdict::alterTab_writeTableConf(Signal* signal, if(coordinatorRef != reference()) { jam(); // Release resources - c_tableRecordPool.getPtr(tabPtr, regAlterTabPtr->m_tablePtrI); + c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI); releaseTableObject(tabPtr.i, false); c_opCreateTable.release(alterTabPtr); c_blockState = BS_IDLE; @@ -5220,6 +5288,10 @@ Dbdict::execDROP_TABLE_REQ(Signal* signal){ jam(); dropTableRef(signal, req, DropTableRef::DropInProgress); return; + case TableRecord::BACKUP_ONGOING: + jam(); + dropTableRef(signal, req, DropTableRef::BackupInProgress); + return; } ndbrequire(ok); @@ -5246,15 +5318,53 @@ Dbdict::execDROP_TABLE_REQ(Signal* signal){ dropTabPtr.p->key = ++c_opRecordSequence; c_opDropTable.add(dropTabPtr); - tablePtr.p->tabState = TableRecord::PREPARE_DROPPING; - dropTabPtr.p->m_request = * req; dropTabPtr.p->m_errorCode = 0; dropTabPtr.p->m_requestType = DropTabReq::OnlineDropTab; dropTabPtr.p->m_coordinatorRef = reference(); dropTabPtr.p->m_coordinatorData.m_gsn = GSN_PREP_DROP_TAB_REQ; dropTabPtr.p->m_coordinatorData.m_block = 0; - prepDropTab_nextStep(signal, dropTabPtr); + + Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex); + Callback c = { safe_cast(&Dbdict::dropTable_backup_mutex_locked), + dropTabPtr.p->key}; + + ndbrequire(mutex.lock(c)); + +} + +void +Dbdict::dropTable_backup_mutex_locked(Signal* signal, + Uint32 callbackData, + Uint32 retValue){ + jamEntry(); + + ndbrequire(retValue == 0); + + DropTableRecordPtr dropTabPtr; + ndbrequire(c_opDropTable.find(dropTabPtr, callbackData)); + + TableRecordPtr tablePtr; + c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId, true); + + Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex); + mutex.unlock(); // ignore response + + if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) + { + jam(); + dropTableRef(signal, &dropTabPtr.p->m_request, + DropTableRef::BackupInProgress); + + c_blockState = BS_IDLE; + c_opDropTable.release(dropTabPtr); + } + else + { + jam(); + tablePtr.p->tabState = TableRecord::PREPARE_DROPPING; + prepDropTab_nextStep(signal, dropTabPtr); + } } void @@ -5974,7 +6084,8 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal) return; }//if - if (tablePtr.p->tabState != TableRecord::DEFINED) { + if (! (tablePtr.p->tabState == TableRecord::DEFINED || + tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)) { jam(); sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined); return; @@ -6110,6 +6221,9 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal) case TableRecord::DEFINED: conf->setTableState(pos, DictTabInfo::StateOnline); break; + case TableRecord::BACKUP_ONGOING: + conf->setTableState(pos, DictTabInfo::StateBackup); + break; default: conf->setTableState(pos, DictTabInfo::StateBroken); break; @@ -6490,7 +6604,8 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) } TableRecordPtr tablePtr; c_tableRecordPool.getPtr(tablePtr, req->getTableId()); - if (tablePtr.p->tabState != TableRecord::DEFINED) { + if (tablePtr.p->tabState != TableRecord::DEFINED && + tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) { jam(); opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable; opPtr.p->m_errorLine = __LINE__; @@ -10795,7 +10910,8 @@ Dbdict::createTrigger_slavePrepare(Signal* signal, OpCreateTriggerPtr opPtr) } TableRecordPtr tablePtr; c_tableRecordPool.getPtr(tablePtr, tableId); - if (tablePtr.p->tabState != TableRecord::DEFINED) { + if (tablePtr.p->tabState != TableRecord::DEFINED && + tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) { jam(); opPtr.p->m_errorCode = CreateTrigRef::InvalidTable; opPtr.p->m_errorLine = __LINE__; @@ -11616,6 +11732,11 @@ Dbdict::alterTrigger_slavePrepare(Signal* signal, OpAlterTriggerPtr opPtr) opPtr.p->m_errorLine = __LINE__; return; } + + if (triggerPtr.p->triggerType == TriggerType::SUBSCRIPTION) + { + opPtr.p->m_request.addRequestFlag(RequestFlag::RF_NOTCTRIGGER); + } } void @@ -12019,7 +12140,9 @@ Dbdict::getMetaTablePtr(TableRecordPtr& tablePtr, Uint32 tableId, Uint32 tableVe } // online flag is not maintained by DICT tablePtr.p->online = - tablePtr.p->isTable() && tablePtr.p->tabState == TableRecord::DEFINED || + tablePtr.p->isTable() && + (tablePtr.p->tabState == TableRecord::DEFINED || + tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) || tablePtr.p->isIndex() && tablePtr.p->indexState == TableRecord::IS_ONLINE; return 0; } diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 68bb9b628d4..e6d2fe44b04 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -150,8 +150,6 @@ public: /** Pointer to last attribute in table */ Uint32 lastAttribute; - /* Temporary record used during add/drop table */ - Uint32 myConnect; #ifdef HAVE_TABLE_REORG /* Second table used by this table (for table reorg) */ Uint32 secondTable; @@ -175,7 +173,8 @@ public: CHECKED = 3, DEFINED = 4, PREPARE_DROPPING = 5, - DROPPING = 6 + DROPPING = 6, + BACKUP_ONGOING = 7 }; TabState tabState; @@ -511,6 +510,8 @@ private: void execBUILDINDXCONF(Signal* signal); void execBUILDINDXREF(Signal* signal); + void execBACKUP_FRAGMENT_REQ(Signal*); + // Util signals used by Event code void execUTIL_PREPARE_CONF(Signal* signal); void execUTIL_PREPARE_REF (Signal* signal); @@ -925,6 +926,8 @@ private: Uint32 m_errorCode; void setErrorCode(Uint32 c){ if(m_errorCode == 0) m_errorCode = c;} + + MutexHandle2<BACKUP_DEFINE_MUTEX> m_define_backup_mutex; /** * When sending stuff around @@ -1942,6 +1945,7 @@ private: bool getIsFailed(Uint32 nodeId) const; + void dropTable_backup_mutex_locked(Signal* signal, Uint32, Uint32); void dropTableRef(Signal * signal, DropTableReq *, DropTableRef::ErrorCode); void printTables(); // For debugging only int handleAlterTab(AlterTabReq * req, @@ -1952,6 +1956,7 @@ private: Uint32 changeMask, Uint32 tableId, CreateTableRecord * regAlterTabPtr); + void alterTable_backup_mutex_locked(Signal* signal, Uint32, Uint32); void alterTableRef(Signal * signal, AlterTableReq *, AlterTableRef::ErrorCode, ParseDictTabInfoRecord* parseRecord = NULL); diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 2a661104347..723792d2e26 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -10290,7 +10290,87 @@ void Dbdih::tableCloseLab(Signal* signal, FileRecordPtr filePtr) * GCP stop detected, * send SYSTEM_ERROR to all other alive nodes */ -void Dbdih::crashSystemAtGcpStop(Signal* signal){ +void Dbdih::crashSystemAtGcpStop(Signal* signal) +{ + switch(cgcpStatus){ + case GCP_NODE_FINISHED: + { + /** + * We're waiting for a GCP save conf + */ + ndbrequire(!c_GCP_SAVEREQ_Counter.done()); + NodeReceiverGroup rg(DBLQH, c_GCP_SAVEREQ_Counter); + signal->theData[0] = 2305; + sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB); + + infoEvent("Detected GCP stop...sending kill to %s", + c_GCP_SAVEREQ_Counter.getText()); + ndbout_c("Detected GCP stop...sending kill to %s", + c_GCP_SAVEREQ_Counter.getText()); + return; + } + case GCP_SAVE_LQH_FINISHED: + ndbout_c("m_copyReason: %d m_waiting: %d", + c_copyGCIMaster.m_copyReason, + c_copyGCIMaster.m_waiting); + break; + } + + ndbout_c("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d", + c_copyGCISlave.m_senderData, + c_copyGCISlave.m_senderRef, + c_copyGCISlave.m_copyReason, + c_copyGCISlave.m_expectedNextWord); + + FileRecordPtr file0Ptr; + file0Ptr.i = crestartInfoFile[0]; + ptrCheckGuard(file0Ptr, cfileFileSize, fileRecord); + FileRecordPtr file1Ptr; + file1Ptr.i = crestartInfoFile[1]; + ptrCheckGuard(file1Ptr, cfileFileSize, fileRecord); + + ndbout_c("file[0] status: %d type: %d reqStatus: %d file1: %d %d %d", + file0Ptr.p->fileStatus, file0Ptr.p->fileType, file0Ptr.p->reqStatus, + file1Ptr.p->fileStatus, file1Ptr.p->fileType, file1Ptr.p->reqStatus + ); + + signal->theData[0] = 404; + signal->theData[1] = file0Ptr.p->fileRef; + EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2); + + signal->theData[0] = 404; + signal->theData[1] = file1Ptr.p->fileRef; + EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2); + + ndbout_c("c_COPY_GCIREQ_Counter = %s", + c_COPY_GCIREQ_Counter.getText()); + ndbout_c("c_COPY_TABREQ_Counter = %s", + c_COPY_TABREQ_Counter.getText()); + ndbout_c("c_CREATE_FRAGREQ_Counter = %s", + c_CREATE_FRAGREQ_Counter.getText()); + ndbout_c("c_DIH_SWITCH_REPLICA_REQ_Counter = %s", + c_DIH_SWITCH_REPLICA_REQ_Counter.getText()); + ndbout_c("c_EMPTY_LCP_REQ_Counter = %s",c_EMPTY_LCP_REQ_Counter.getText()); + ndbout_c("c_END_TOREQ_Counter = %s", c_END_TOREQ_Counter.getText()); + ndbout_c("c_GCP_COMMIT_Counter = %s", c_GCP_COMMIT_Counter.getText()); + ndbout_c("c_GCP_PREPARE_Counter = %s", c_GCP_PREPARE_Counter.getText()); + ndbout_c("c_GCP_SAVEREQ_Counter = %s", c_GCP_SAVEREQ_Counter.getText()); + ndbout_c("c_INCL_NODEREQ_Counter = %s", c_INCL_NODEREQ_Counter.getText()); + ndbout_c("c_MASTER_GCPREQ_Counter = %s", + c_MASTER_GCPREQ_Counter.getText()); + ndbout_c("c_MASTER_LCPREQ_Counter = %s", + c_MASTER_LCPREQ_Counter.getText()); + ndbout_c("c_START_INFOREQ_Counter = %s", + c_START_INFOREQ_Counter.getText()); + ndbout_c("c_START_RECREQ_Counter = %s", c_START_RECREQ_Counter.getText()); + ndbout_c("c_START_TOREQ_Counter = %s", c_START_TOREQ_Counter.getText()); + ndbout_c("c_STOP_ME_REQ_Counter = %s", c_STOP_ME_REQ_Counter.getText()); + ndbout_c("c_TC_CLOPSIZEREQ_Counter = %s", + c_TC_CLOPSIZEREQ_Counter.getText()); + ndbout_c("c_TCGETOPSIZEREQ_Counter = %s", + c_TCGETOPSIZEREQ_Counter.getText()); + ndbout_c("c_UPDATE_TOREQ_Counter = %s", c_UPDATE_TOREQ_Counter.getText()); + NodeRecordPtr nodePtr; for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { jam(); diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 725ea04c148..a15d54c0b28 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -169,6 +169,8 @@ void Dblqh::execTUP_COM_UNBLOCK(Signal* signal) /* ------------------------------------------------------------------------- */ void Dblqh::systemError(Signal* signal) { + signal->theData[0] = 2304; + execDUMP_STATE_ORD(signal); progError(0, 0); }//Dblqh::systemError() @@ -12598,6 +12600,22 @@ void Dblqh::lastWriteInFileLab(Signal* signal) void Dblqh::writePageZeroLab(Signal* signal) { + if (false && logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM) + { + if (logPartPtr.p->firstLogQueue == RNIL) + { + jam(); + logPartPtr.p->logPartState = LogPartRecord::IDLE; + ndbout_c("resetting logPartState to IDLE"); + } + else + { + jam(); + logPartPtr.p->logPartState = LogPartRecord::ACTIVE; + ndbout_c("resetting logPartState to ACTIVE"); + } + } + logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING; /*---------------------------------------------------------------------------*/ /* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE */ @@ -15661,6 +15679,7 @@ void Dblqh::warningHandlerLab(Signal* signal) void Dblqh::systemErrorLab(Signal* signal) { + systemError(signal); progError(0, 0); /*************************************************************************>*/ /* WE WANT TO INVOKE AN IMMEDIATE ERROR HERE SO WE GET THAT BY */ @@ -18526,8 +18545,65 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) return; } + Uint32 arg= dumpState->args[0]; + if(arg == 2304 || arg == 2305) + { + jam(); + Uint32 i; + GcpRecordPtr gcp; gcp.i = RNIL; + for(i = 0; i<4; i++) + { + logPartPtr.i = i; + ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord); + ndbout_c("LP %d state: %d WW_Gci: %d gcprec: %d flq: %d currfile: %d tailFileNo: %d logTailMbyte: %d", + i, + logPartPtr.p->logPartState, + logPartPtr.p->waitWriteGciLog, + logPartPtr.p->gcprec, + logPartPtr.p->firstLogQueue, + logPartPtr.p->currentLogfile, + logPartPtr.p->logTailFileNo, + logPartPtr.p->logTailMbyte); + + if(gcp.i == RNIL && logPartPtr.p->gcprec != RNIL) + gcp.i = logPartPtr.p->gcprec; + LogFileRecordPtr logFilePtr; + Uint32 first= logFilePtr.i= logPartPtr.p->firstLogfile; + do + { + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage", + logFilePtr.p->fileNo, + logFilePtr.i, + logFilePtr.p->fileChangeState, + logFilePtr.p->logFileStatus, + logFilePtr.p->currentMbyte, + logFilePtr.p->currentFilepage); + logFilePtr.i = logFilePtr.p->nextLogFile; + } while(logFilePtr.i != first); + } + + if(gcp.i != RNIL) + { + ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord); + for(i = 0; i<4; i++) + { + ndbout_c(" GCP %d file: %d state: %d sync: %d page: %d word: %d", + i, gcp.p->gcpFilePtr[i], gcp.p->gcpLogPartState[i], + gcp.p->gcpSyncReady[i], + gcp.p->gcpPageNo[i], + gcp.p->gcpWordNo[i]); + } + } + if(arg== 2305) + { + progError(__LINE__, ERR_SYSTEM_ERROR, + "Shutting down node due to failed handling of GCP_SAVEREQ"); + + } + } }//Dblqh::execDUMP_STATE_ORD() void Dblqh::execSET_VAR_REQ(Signal* signal) diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp index f76440a462a..45073b63a5d 100644 --- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp +++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp @@ -96,6 +96,7 @@ AsyncFile::AsyncFile() : theReportTo(0), theMemoryChannelPtr(NULL) { + m_current_request= m_last_request= 0; } void @@ -177,6 +178,7 @@ AsyncFile::run() endReq(); return; }//if + m_current_request= request; switch (request->action) { case Request:: open: openReq(request); @@ -226,7 +228,11 @@ AsyncFile::run() abort(); break; }//switch - theReportTo->writeChannel(request); + m_last_request= request; + m_current_request= 0; + + // No need to signal as ndbfs only uses tryRead + theReportTo->writeChannelNoSignal(request); }//while }//AsyncFile::run() @@ -1031,3 +1037,60 @@ void printErrorAndFlags(Uint32 used_flags) { } #endif + +NdbOut& +operator<<(NdbOut& out, const Request& req) +{ + out << "[ Request: file: " << hex << req.file + << " userRef: " << hex << req.theUserReference + << " userData: " << dec << req.theUserPointer + << " theFilePointer: " << req.theFilePointer + << " action: "; + switch(req.action){ + case Request::open: + out << "open"; + break; + case Request::close: + out << "close"; + break; + case Request::closeRemove: + out << "closeRemove"; + break; + case Request::read: // Allways leave readv directly after + out << "read"; + break; + case Request::readv: + out << "readv"; + break; + case Request::write:// Allways leave writev directly after + out << "write"; + break; + case Request::writev: + out << "writev"; + break; + case Request::writeSync:// Allways leave writevSync directly after + out << "writeSync"; + break; + // writeSync because SimblockAsyncFileSystem depends on it + case Request::writevSync: + out << "writevSync"; + break; + case Request::sync: + out << "sync"; + break; + case Request::end: + out << "end"; + break; + case Request::append: + out << "append"; + break; + case Request::rmrf: + out << "rmrf"; + break; + default: + out << (Uint32)req.action; + break; + } + out << " ]"; + return out; +} diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp index 2176c93c5d5..997bf40fe2a 100644 --- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp +++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp @@ -160,6 +160,7 @@ public: Uint32 theTrace; }; +NdbOut& operator <<(NdbOut&, const Request&); inline void @@ -173,6 +174,7 @@ Request::set(BlockReference userReference, class AsyncFile { + friend class Ndbfs; public: AsyncFile(); ~AsyncFile(); @@ -188,6 +190,7 @@ public: bool isOpen(); Filename theFileName; + Request *m_current_request, *m_last_request; private: void openReq(Request *request); diff --git a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp index 349cccdbcb4..460ad3f614a 100644 --- a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp +++ b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp @@ -68,7 +68,7 @@ class CircularIndex { public: inline CircularIndex( int start= 0,int size=256 ); - operator int (); + operator int () const; CircularIndex& operator ++ (); friend int full( const CircularIndex& write, const CircularIndex& read ); friend int empty( const CircularIndex& write, const CircularIndex& read ); @@ -77,7 +77,7 @@ private: int theIndex; }; -inline CircularIndex::operator int () +inline CircularIndex::operator int () const { return theIndex; } diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp index 03911d195ec..9037bbad765 100644 --- a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp +++ b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp @@ -84,7 +84,8 @@ public: MemoryChannel( int size= 256); virtual ~MemoryChannel( ); - virtual void writeChannel( T *t); + void writeChannel( T *t); + void writeChannelNoSignal( T *t); T* readChannel(); T* tryReadChannel(); @@ -96,8 +97,20 @@ private: NdbMutex* theMutexPtr; NdbCondition* theConditionPtr; + template<class U> + friend NdbOut& operator<<(NdbOut& out, const MemoryChannel<U> & chn); }; +template <class T> +NdbOut& operator<<(NdbOut& out, const MemoryChannel<T> & chn) +{ + NdbMutex_Lock(chn.theMutexPtr); + out << "[ theSize: " << chn.theSize + << " theReadIndex: " << (int)chn.theReadIndex + << " theWriteIndex: " << (int)chn.theWriteIndex << " ]"; + NdbMutex_Unlock(chn.theMutexPtr); + return out; +} template <class T> MemoryChannel<T>::MemoryChannel( int size): theSize(size), @@ -127,6 +140,15 @@ template <class T> void MemoryChannel<T>::writeChannel( T *t) NdbCondition_Signal(theConditionPtr); } +template <class T> void MemoryChannel<T>::writeChannelNoSignal( T *t) +{ + + NdbMutex_Lock(theMutexPtr); + if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort(); + theChannel[theWriteIndex]= t; + ++theWriteIndex; + NdbMutex_Unlock(theMutexPtr); +} template <class T> T* MemoryChannel<T>::readChannel() { @@ -149,8 +171,6 @@ template <class T> T* MemoryChannel<T>::tryReadChannel() { T* tmp= 0; NdbMutex_Lock(theMutexPtr); - NdbCondition_WaitTimeout(theConditionPtr, - theMutexPtr, 0); if ( !empty(theWriteIndex, theReadIndex) ) { tmp= theChannel[theReadIndex]; diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp index 6f848d7fe16..d6b19c8f872 100644 --- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp +++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp @@ -1006,6 +1006,30 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal) } return; } + + if(signal->theData[0] == 404) + { + ndbrequire(signal->getLength() == 2); + Uint32 file= signal->theData[1]; + AsyncFile* openFile = theOpenFiles.find(file); + ndbrequire(openFile); + ndbout_c("File: %s %p", openFile->theFileName.c_str(), openFile); + Request* curr = openFile->m_current_request; + Request* last = openFile->m_last_request; + if(curr) + ndbout << "Current request: " << *curr << endl; + if(last) + ndbout << "Last request: " << *last << endl; + + ndbout << "theReportTo " << *openFile->theReportTo << endl; + ndbout << "theMemoryChannelPtr" << *openFile->theMemoryChannelPtr << endl; + + ndbout << "All files: " << endl; + for (unsigned i = 0; i < theFiles.size(); i++){ + AsyncFile* file = theFiles[i]; + ndbout_c("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED"); + } + } }//Ndbfs::execDUMP_STATE_ORD() @@ -1016,3 +1040,4 @@ template class Vector<AsyncFile*>; template class Vector<OpenFiles::OpenFileItem>; template class MemoryChannel<Request>; template class Pool<Request>; +template NdbOut& operator<<(NdbOut&, const MemoryChannel<Request>&); diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 34d1614d043..eccd175b1b9 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1244,6 +1244,7 @@ objectStateMapping[] = { { DictTabInfo::StateBuilding, NdbDictionary::Object::StateBuilding }, { DictTabInfo::StateDropping, NdbDictionary::Object::StateDropping }, { DictTabInfo::StateOnline, NdbDictionary::Object::StateOnline }, + { DictTabInfo::StateBackup, NdbDictionary::Object::StateBackup }, { DictTabInfo::StateBroken, NdbDictionary::Object::StateBroken }, { -1, -1 } }; diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 840d358f225..ad5523d32eb 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -344,6 +344,8 @@ ErrorBundle ErrorCodes[] = { { 743, SE, "Unsupported character set in table or index" }, { 744, SE, "Character string is invalid for given character set" }, { 745, SE, "Distribution key not supported for char attribute (use binary attribute)" }, + { 761, SE, "Unable to drop table as backup is in progress" }, + { 762, SE, "Unable to alter table as backup is in progress" }, { 241, SE, "Invalid schema object version" }, { 283, SE, "Table is being dropped" }, { 284, SE, "Table not defined in transaction coordinator" }, diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp index 05137710609..dde60c1300d 100644 --- a/ndb/test/include/HugoOperations.hpp +++ b/ndb/test/include/HugoOperations.hpp @@ -41,6 +41,11 @@ public: int numRecords = 1, int updatesValue = 0); + int pkWriteRecord(Ndb*, + int recordNo, + int numRecords = 1, + int updatesValue = 0); + int pkReadRecord(Ndb*, int recordNo, int numRecords = 1, @@ -97,6 +102,10 @@ public: NdbIndexScanOperation* pIndexScanOp; NDBT_ResultRow& get_row(Uint32 idx) { return *rows[idx];} + + int execute_async(Ndb*, ExecType, AbortOption = AbortOnError); + int wait_async(Ndb*, int timeout = -1); + protected: void allocRows(int rows); void deallocRows(); @@ -109,6 +118,11 @@ protected: struct RsPair { NdbScanOperation* m_result_set; int records; }; Vector<RsPair> m_result_sets; Vector<RsPair> m_executed_result_sets; + + int m_async_reply; + int m_async_return; + friend void HugoOperations_async_callback(int, NdbConnection*, void*); + void callback(int res, NdbConnection*); }; #endif diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp index 7a6f11a6bb9..1ab348e735f 100644 --- a/ndb/test/ndbapi/testBackup.cpp +++ b/ndb/test/ndbapi/testBackup.cpp @@ -138,6 +138,61 @@ int runBackupOne(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBackupLoop(NDBT_Context* ctx, NDBT_Step* step){ + NdbBackup backup(GETNDB(step)->getNodeId()+1); + unsigned backupId = 0; + + int loops = ctx->getNumLoops(); + while(!ctx->isTestStopped() && loops--) + { + if (backup.start(backupId) == -1) + { + sleep(1); + loops++; + } + else + { + sleep(3); + } + } + + ctx->stopTest(); + return NDBT_OK; +} + +int +runDDL(NDBT_Context* ctx, NDBT_Step* step){ + Ndb* pNdb= GETNDB(step); + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + const int tables = NDBT_Tables::getNumTables(); + while(!ctx->isTestStopped()) + { + const int tab_no = rand() % (tables); + NdbDictionary::Table tab = *NDBT_Tables::getTable(tab_no); + BaseString name= tab.getName(); + name.appfmt("-%d", step->getStepNo()); + tab.setName(name.c_str()); + if(pDict->createTable(tab) == 0) + { + HugoTransactions hugoTrans(* pDict->getTable(name.c_str())); + if (hugoTrans.loadTable(pNdb, 10000) != 0){ + return NDBT_FAILED; + } + + while(pDict->dropTable(tab.getName()) != 0 && + pDict->getNdbError().code != 4009) + g_err << pDict->getNdbError() << endl; + + sleep(1); + + } + } + return NDBT_OK; +} + + int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){ NdbRestarter restarter; @@ -417,6 +472,15 @@ TESTCASE("BackupOne", VERIFIER(runVerifyOne); FINALIZER(runClearTable); } +TESTCASE("BackupDDL", + "Test that backup and restore works on with DDL ongoing\n" + "1. Backups and DDL (create,drop,table.index)"){ + INITIALIZER(runLoadTable); + STEP(runBackupLoop); + STEP(runDDL); + STEP(runDDL); + FINALIZER(runClearTable); +} TESTCASE("BackupBank", "Test that backup and restore works during transaction load\n" " by backing up the bank" diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp index 137a1d51d82..8a66c120b51 100644 --- a/ndb/test/ndbapi/testNdbApi.cpp +++ b/ndb/test/ndbapi/testNdbApi.cpp @@ -1037,6 +1037,8 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){ return result; } +#define C2(x) { int _x= (x); if(_x == 0) return NDBT_FAILED; } + int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; const NdbDictionary::Table* pTab = ctx->getTab(); @@ -1044,228 +1046,76 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ HugoOperations hugoOps(*pTab); Ndb* pNdb = GETNDB(step); - Uint32 lm; - - NdbConnection* pCon = pNdb->startTransaction(); - if (pCon == NULL){ - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - NdbOperation* pOp = pCon->getNdbOperation(pTab->getName()); - if (pOp == NULL){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - if (pOp->readTuple(NdbOperation::LM_Exclusive) != 0){ - pNdb->closeTransaction(pCon); - ERR(pOp->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() == true){ - if(hugoOps.equalForAttr(pOp, a, 1) != 0){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() != true){ - if (pOp->getValue(pTab->getColumn(a)->getName()) == NULL) { - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - int check = pCon->execute(NoCommit); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - - pOp = pCon->getNdbOperation(pTab->getName()); - if (pOp == NULL){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - if (pOp->deleteTuple() != 0){ - pNdb->closeTransaction(pCon); - ERR(pOp->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() == true){ - if(hugoOps.equalForAttr(pOp, a, 1) != 0){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - check = pCon->execute(NoCommit); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - - pOp = pCon->getNdbOperation(pTab->getName()); - if (pOp == NULL){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - if (pOp->writeTuple() != 0){ - pNdb->closeTransaction(pCon); - ERR(pOp->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() == true){ - if(hugoOps.equalForAttr(pOp, a, 1) != 0){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() != true){ - if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0) - { - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - check = pCon->execute(NoCommit); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - pOp = pCon->getNdbOperation(pTab->getName()); - if (pOp == NULL){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - if (pOp->writeTuple() != 0){ - pNdb->closeTransaction(pCon); - ERR(pOp->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() == true){ - if(hugoOps.equalForAttr(pOp, a, 1) != 0){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() != true){ - if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0) - { - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - check = pCon->execute(NoCommit); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - - check = pCon->execute(Rollback); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - - pCon->close(); + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Exclusive) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkWriteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + + Ndb ndb2("TEST_DB"); + C2(ndb2.init() == 0); + C2(ndb2.waitUntilReady() == 0); + HugoOperations hugoOps2(*pTab); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps2.startTransaction(&ndb2) == 0); + C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0); + C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps2.wait_async(&ndb2) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + C2(hugoOps2.closeTransaction(&ndb2) == 0); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps2.startTransaction(&ndb2) == 0); + C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0); + C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps2.wait_async(&ndb2) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + C2(hugoOps2.closeTransaction(&ndb2) == 0); - pCon = pNdb->startTransaction(); - if (pCon == NULL){ - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - pOp = pCon->getNdbOperation(pTab->getName()); - if (pOp == NULL){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - - if (pOp->writeTuple() != 0){ - pNdb->closeTransaction(pCon); - ERR(pOp->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() == true){ - if(hugoOps.equalForAttr(pOp, a, 1) != 0){ - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if (pTab->getColumn(a)->getPrimaryKey() != true){ - if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0) - { - ERR(pCon->getNdbError()); - pNdb->closeTransaction(pCon); - return NDBT_FAILED; - } - } - } - - check = pCon->execute(Commit); - if (check == 0){ - ndbout << "execute worked" << endl; - } else { - ERR(pCon->getNdbError()); - result = NDBT_FAILED; - } - return result; } @@ -1442,7 +1292,6 @@ TESTCASE("ReadWithoutGetValue", } TESTCASE("Bug_11133", "Test ReadEx-Delete-Write\n"){ - INITIALIZER(runLoadTable); INITIALIZER(runBug_11133); FINALIZER(runClearTable); } diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 5d7d7f58f89..8b44594a9b5 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -54,6 +54,10 @@ max-time: 600 cmd: atrt-testBackup args: -n BackupOne T1 T6 T3 I3 +max-time: 600 +cmd: atrt-testBackup +args: -n BackupDDL T1 + # BASIC FUNCTIONALITY max-time: 500 cmd: testBasic diff --git a/ndb/test/run-test/ndb-autotest.sh b/ndb/test/run-test/ndb-autotest.sh index 573a9953924..4228d2354d3 100755 --- a/ndb/test/run-test/ndb-autotest.sh +++ b/ndb/test/run-test/ndb-autotest.sh @@ -84,7 +84,7 @@ fi for i in $vars do t=`echo echo \\$$i` - if [ -z `eval $t` ] + if [ -z "`eval $t`" ] then echo "Invalid config: $conf, variable $i is not set" exit @@ -301,8 +301,8 @@ choose_conf(){ echo "$test_dir/conf-$1.txt" else echo "Unable to find conf file looked for" 1>&2 - echo "$testdir/conf-$1-$HOST.txt and" 1>&2 - echo "$testdir/conf-$1.txt" 1>&2 + echo "$test_dir/conf-$1-$HOST.txt and" 1>&2 + echo "$test_dir/conf-$1.txt" 1>&2 exit fi } diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index f9a09eddd1f..ff9e0b5ad21 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -16,7 +16,6 @@ #include <HugoOperations.hpp> - int HugoOperations::startTransaction(Ndb* pNdb){ if (pTrans != NULL){ @@ -226,6 +225,48 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, return NDBT_OK; } +int HugoOperations::pkWriteRecord(Ndb* pNdb, + int recordNo, + int numRecords, + int updatesValue){ + + int a, check; + for(int r=0; r < numRecords; r++){ + NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + + check = pOp->writeTuple(); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + + // Define primary keys + for(a = 0; a<tab.getNoOfColumns(); a++){ + if (tab.getColumn(a)->getPrimaryKey() == true){ + if(equalForAttr(pOp, a, r+recordNo) != 0){ + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + } + + // Define attributes to update + for(a = 0; a<tab.getNoOfColumns(); a++){ + if (tab.getColumn(a)->getPrimaryKey() == false){ + if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + } + } + return NDBT_OK; +} + int HugoOperations::pkDeleteRecord(Ndb* pNdb, int recordNo, int numRecords){ @@ -367,16 +408,57 @@ int HugoOperations::execute_Rollback(Ndb* pNdb){ return NDBT_OK; } -HugoOperations::HugoOperations(const NdbDictionary::Table& _tab, - const NdbDictionary::Index* idx): - UtilTransactions(_tab, idx), +void +HugoOperations_async_callback(int res, NdbConnection* pCon, void* ho) +{ + ((HugoOperations*)ho)->callback(res, pCon); +} + +void +HugoOperations::callback(int res, NdbConnection* pCon) +{ + assert(pCon == pTrans); + m_async_reply= 1; + m_async_return= res; +} + +int +HugoOperations::execute_async(Ndb* pNdb, ExecType et, AbortOption eao){ + + m_async_reply= 0; + pTrans->executeAsynchPrepare(et, + HugoOperations_async_callback, + this, + eao); + + pNdb->sendPreparedTransactions(); + + return NDBT_OK; +} + +int +HugoOperations::wait_async(Ndb* pNdb, int timeout) +{ + pNdb->pollNdb(1000); + + if(m_async_reply) + { + return m_async_return; + } + ndbout_c("wait returned nothing..."); + return -1; +} + +HugoOperations::HugoOperations(const NdbDictionary::Table& _tab): + UtilTransactions(_tab), calc(_tab) { } HugoOperations::~HugoOperations(){ deallocRows(); - if (pTrans != NULL){ + if (pTrans != NULL) + { pTrans->close(); pTrans = NULL; } diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp index e2bf7f0bfae..24116f22784 100644 --- a/ndb/tools/drop_index.cpp +++ b/ndb/tools/drop_index.cpp @@ -35,7 +35,7 @@ static struct my_option my_long_options[] = static void usage() { char desc[] = - "<indexname>+\n"\ + "[<table> <index>]+\n"\ "This program will drop index(es) in Ndb\n"; ndb_std_print_version(); my_print_help(my_long_options); @@ -76,10 +76,10 @@ int main(int argc, char** argv){ } int res = 0; - for(int i = 0; i<argc; i++){ - ndbout << "Dropping index " << argv[i] << "..."; + for(int i = 0; i+1<argc; i += 2){ + ndbout << "Dropping index " << argv[i] << "/" << argv[i+1] << "..."; int tmp; - if((tmp = MyNdb.getDictionary()->dropIndex(argv[i], 0)) != 0){ + if((tmp = MyNdb.getDictionary()->dropIndex(argv[i+1], argv[i])) != 0){ ndbout << endl << MyNdb.getDictionary()->getNdbError() << endl; res = tmp; } else { diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp index b4a2235f73b..fa078f7d351 100644 --- a/ndb/tools/listTables.cpp +++ b/ndb/tools/listTables.cpp @@ -131,6 +131,9 @@ list(const char * tabname, case NdbDictionary::Object::StateOnline: strcpy(state, "Online"); break; + case NdbDictionary::Object::StateBackup: + strcpy(state, "Backup"); + break; case NdbDictionary::Object::StateBroken: strcpy(state, "Broken"); break; |