summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <joreland@mysql.com>2005-07-20 14:25:46 +0200
committerunknown <joreland@mysql.com>2005-07-20 14:25:46 +0200
commit46c627f34c77f7e103d7afa2fc54451c1ff9d28a (patch)
tree84ee386073b270372be1ac5bcbaffe380d94f906
parent21038e65daf34d2348706775b6f45e91268969f8 (diff)
parent5aac38c084590e894f2e82b4cdef349dcc14e3f1 (diff)
downloadmariadb-git-46c627f34c77f7e103d7afa2fc54451c1ff9d28a.tar.gz
Merge joreland@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/jonas/src/mysql-4.1-push
-rw-r--r--ndb/include/kernel/signaldata/AlterTable.hpp3
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp1
-rw-r--r--ndb/include/kernel/signaldata/DropTable.hpp3
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp1
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp45
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp19
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp309
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp11
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp4
-rw-r--r--ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp14
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp1
-rw-r--r--ndb/src/ndbapi/ndberror.c2
-rw-r--r--ndb/test/include/HugoOperations.hpp14
-rw-r--r--ndb/test/ndbapi/testBackup.cpp64
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp291
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt4
-rwxr-xr-xndb/test/run-test/ndb-autotest.sh6
-rw-r--r--ndb/test/src/HugoOperations.cpp91
-rw-r--r--ndb/tools/drop_index.cpp8
-rw-r--r--ndb/tools/listTables.cpp3
20 files changed, 552 insertions, 342 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 a2f9fcc9799..48c24125ae4 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -209,6 +209,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 0e4f506c604..85615f3aa66 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -118,6 +118,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 b0ce5c390cb..3334d69ae89 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 5921c3b63eb..3313e22fe3a 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -6198,7 +6198,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 0c4d20ca248..618bea377a2 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -1186,6 +1186,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()
@@ -1341,7 +1343,6 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->tabState = TableRecord::NOT_DEFINED;
tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
tablePtr.p->storageType = DictTabInfo::MainMemory;
- tablePtr.p->myConnect = RNIL;
tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
tablePtr.p->fragmentKeyType = DictTabInfo::PrimaryKey;
memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName));
@@ -2785,6 +2786,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
@@ -2835,6 +2857,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();
@@ -2854,7 +2880,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();
@@ -2862,7 +2887,7 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal)
return;
}
- regAlterTabPtr->m_changeMask = changeMask;
+ alterTabPtr.p->m_changeMask = changeMask;
parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
parseRecord.errorCode = 0;
@@ -2882,20 +2907,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());
@@ -2903,27 +2925,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,
@@ -2998,9 +3067,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;
@@ -3034,6 +3102,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);
@@ -3064,23 +3136,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);
@@ -3105,7 +3177,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;
@@ -3133,7 +3205,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();
@@ -3197,9 +3269,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): {
@@ -3207,7 +3278,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;
@@ -3218,14 +3289,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;
@@ -3237,7 +3308,7 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){
}
else {
jam();
- regAlterTabPtr->m_alterTableFailed = true;
+ alterTabPtr.p->m_alterTableFailed = true;
}
break;
}
@@ -3261,8 +3332,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;
}
@@ -3284,7 +3355,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): {
@@ -3328,23 +3398,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;
@@ -3355,14 +3425,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;
@@ -3384,14 +3454,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;
@@ -3411,18 +3481,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 {
@@ -3431,18 +3501,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;
@@ -3473,7 +3543,7 @@ void Dbdict::printTables()
}
int Dbdict::handleAlterTab(AlterTabReq * req,
- CreateTableRecord * regAlterTabPtr,
+ CreateTableRecord * alterTabPtrP,
TableRecordPtr origTablePtr,
TableRecordPtr newTablePtr)
{
@@ -3488,7 +3558,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;
@@ -3507,7 +3577,7 @@ int Dbdict::handleAlterTab(AlterTabReq * req,
void Dbdict::revertAlterTable(Signal * signal,
Uint32 changeMask,
Uint32 tableId,
- CreateTableRecord * regAlterTabPtr)
+ CreateTableRecord * alterTabPtrP)
{
if (AlterTableReq::getNameFlag(changeMask)) {
jam();
@@ -3522,7 +3592,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
@@ -3546,16 +3616,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);
@@ -3571,10 +3640,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();
@@ -3589,7 +3657,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;
@@ -5005,6 +5073,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);
@@ -5031,15 +5103,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
@@ -5755,7 +5865,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;
@@ -5891,6 +6002,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;
@@ -6270,7 +6384,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__;
@@ -10565,7 +10680,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__;
@@ -11386,6 +11502,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
@@ -11747,7 +11868,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 5fc4742e829..48dc2d2c2d5 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -149,8 +149,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;
@@ -174,7 +172,8 @@ public:
CHECKED = 3,
DEFINED = 4,
PREPARE_DROPPING = 5,
- DROPPING = 6
+ DROPPING = 6,
+ BACKUP_ONGOING = 7
};
TabState tabState;
@@ -502,6 +501,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);
@@ -894,6 +895,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
@@ -1908,6 +1911,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,
@@ -1918,6 +1922,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/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index f76440a462a..c0ffa722f1c 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -226,7 +226,9 @@ AsyncFile::run()
abort();
break;
}//switch
- theReportTo->writeChannel(request);
+
+ // No need to signal as ndbfs only uses tryRead
+ theReportTo->writeChannelNoSignal(request);
}//while
}//AsyncFile::run()
diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
index 03911d195ec..6bb9684f3ca 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();
@@ -127,6 +128,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 +159,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/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 645aa333ea7..27fd70cd0f4 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -1150,6 +1150,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 04c25f31387..6fdc75fbe7e 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -312,6 +312,8 @@ ErrorBundle ErrorCodes[] = {
{ 742, SE, "Unsupported attribute type in index" },
{ 743, SE, "Unsupported character set in table or index" },
{ 744, SE, "Character string is invalid for given character set" },
+ { 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 a23d3018f47..34b2edc2ae8 100644
--- a/ndb/test/include/HugoOperations.hpp
+++ b/ndb/test/include/HugoOperations.hpp
@@ -38,6 +38,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,
@@ -88,6 +93,10 @@ public:
NdbScanOperation::LM_CommittedRead,
int numRecords = 1);
+
+ int execute_async(Ndb*, ExecType, AbortOption = AbortOnError);
+ int wait_async(Ndb*, int timeout = -1);
+
protected:
void allocRows(int rows);
void deallocRows();
@@ -102,6 +111,11 @@ protected:
Vector<RsPair> m_executed_result_sets;
NdbConnection* pTrans;
+
+ 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 bea5d5307e2..14198c250c7 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 de731a5eeec..3a06269f8dc 100644
--- a/ndb/test/ndbapi/testNdbApi.cpp
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -1049,6 +1049,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();
@@ -1056,228 +1058,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;
}
@@ -1359,7 +1209,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 a28f8fe0bd0..fc04664564f 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 8e6603ec6ff..6b1a1ca395b 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){
@@ -199,6 +198,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){
@@ -399,16 +440,58 @@ int HugoOperations::execute_Rollback(Ndb* pNdb){
return NDBT_OK;
}
+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),
- pTrans(NULL){
-
+ pTrans(NULL)
+{
}
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 2fcba41bd11..69c8345fdb6 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);
@@ -73,10 +73,10 @@ int main(int argc, char** argv){
ndbout << "Waiting for ndb to become ready..." << endl;
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 064ec299ef9..eb0c1c53c2d 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;