Commit d88e5766 authored by stewart@mysql.com's avatar stewart@mysql.com

WL#2868 Fix backup trigger handling

BACKUP previous set up triggers using DICT.
This lead to all kind of trouble.
An smaller alternative to using SUMA for backup
  is to just make BACKUP handle triggers to TUP directly.

This way all triggers will be totally local,
  and error handling is much simpler.

--- old impl.

Start: Master recives GSN_DEFINE_BACKUP_CONF from all participants
Master sends CREATE_TRIG_REQ for all tables to local DICT (dict master)
Master sends START_BACKUP_REQ to all paricipants with trigger ids from DICT
Master sends ALTER_TRIG_REQ (online) to local DICT
Master waits for GCP
Master starts distributed scan
When scan has finished
Master waits for GCP
Master sends DROP_TRIGGER to local DICT
Master sends STOP_BACKUP_REQ to all participants

--- new impl.

Start: Master recives GSN_DEFINE_BACKUP_CONF from all participants
Master sends START_BACKUP_REQ to all paricipants
  Participand sends CREATE_TRIG_REQ for all tables to local TUP
Master waits for GCP
Master starts distributed scan
When scan has finished
Master waits for GCP
Master sends STOP_BACKUP_REQ to all participants
  Participant sends DROP_TRIGGER to local TUP

Changes:
All trigger handling is _local_
 This implies, that abort (e.g due to node failure) can be _local_


fix testBackup test so that it will run successfully with the (now correct)
backup trigger code.
parent 55b30563
...@@ -139,21 +139,11 @@ class StartBackupReq { ...@@ -139,21 +139,11 @@ class StartBackupReq {
friend bool printSTART_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16); friend bool printSTART_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( MaxTableTriggers = 4 ); STATIC_CONST( SignalLength = 2 );
STATIC_CONST( HeaderLength = 5 );
STATIC_CONST( TableTriggerLength = 4);
private: private:
Uint32 backupId; Uint32 backupId;
Uint32 backupPtr; Uint32 backupPtr;
Uint32 signalNo;
Uint32 noOfSignals;
Uint32 noOfTableTriggers;
struct TableTriggers {
Uint32 tableId;
Uint32 triggerIds[3];
} tableTriggers[MaxTableTriggers];
}; };
class StartBackupRef { class StartBackupRef {
...@@ -169,7 +159,7 @@ class StartBackupRef { ...@@ -169,7 +159,7 @@ class StartBackupRef {
friend bool printSTART_BACKUP_REF(FILE *, const Uint32 *, Uint32, Uint16); friend bool printSTART_BACKUP_REF(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 5 ); STATIC_CONST( SignalLength = 4 );
enum ErrorCode { enum ErrorCode {
FailedToAllocateTriggerRecord = 1 FailedToAllocateTriggerRecord = 1
...@@ -177,7 +167,6 @@ public: ...@@ -177,7 +167,6 @@ public:
private: private:
Uint32 backupId; Uint32 backupId;
Uint32 backupPtr; Uint32 backupPtr;
Uint32 signalNo;
Uint32 errorCode; Uint32 errorCode;
Uint32 nodeId; Uint32 nodeId;
}; };
...@@ -195,12 +184,11 @@ class StartBackupConf { ...@@ -195,12 +184,11 @@ class StartBackupConf {
friend bool printSTART_BACKUP_CONF(FILE *, const Uint32 *, Uint32, Uint16); friend bool printSTART_BACKUP_CONF(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 3 ); STATIC_CONST( SignalLength = 2 );
private: private:
Uint32 backupId; Uint32 backupId;
Uint32 backupPtr; Uint32 backupPtr;
Uint32 signalNo;
}; };
class BackupFragmentReq { class BackupFragmentReq {
......
...@@ -48,16 +48,8 @@ printDEFINE_BACKUP_CONF(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){ ...@@ -48,16 +48,8 @@ printDEFINE_BACKUP_CONF(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){
bool bool
printSTART_BACKUP_REQ(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){ printSTART_BACKUP_REQ(FILE * out, const Uint32 * data, Uint32 l, Uint16 bno){
StartBackupReq* sig = (StartBackupReq*)data; StartBackupReq* sig = (StartBackupReq*)data;
fprintf(out, " backupPtr: %d backupId: %d signalNo: %d of %d\n", fprintf(out, " backupPtr: %d backupId: %d\n",
sig->backupPtr, sig->backupId, sig->backupPtr, sig->backupId);
sig->signalNo + 1, sig->noOfSignals);
for(Uint32 i = 0; i<sig->noOfTableTriggers; i++)
fprintf(out,
" Table: %d Triggers = [ insert: %d update: %d delete: %d ]\n",
sig->tableTriggers[i].tableId,
sig->tableTriggers[i].triggerIds[TriggerEvent::TE_INSERT],
sig->tableTriggers[i].triggerIds[TriggerEvent::TE_UPDATE],
sig->tableTriggers[i].triggerIds[TriggerEvent::TE_DELETE]);
return true; return true;
} }
......
...@@ -501,12 +501,6 @@ const TriggerEvent::Value triggerEventValues[] = { ...@@ -501,12 +501,6 @@ const TriggerEvent::Value triggerEventValues[] = {
TriggerEvent::TE_DELETE TriggerEvent::TE_DELETE
}; };
const char* triggerNameFormat[] = {
"NDB$BACKUP_%d_%d_INSERT",
"NDB$BACKUP_%d_%d_UPDATE",
"NDB$BACKUP_%d_%d_DELETE"
};
const Backup::State const Backup::State
Backup::validSlaveTransitions[] = { Backup::validSlaveTransitions[] = {
INITIAL, DEFINING, INITIAL, DEFINING,
...@@ -776,7 +770,6 @@ Backup::checkNodeFail(Signal* signal, ...@@ -776,7 +770,6 @@ Backup::checkNodeFail(Signal* signal,
ref->backupPtr = ptr.i; ref->backupPtr = ptr.i;
ref->backupId = ptr.p->backupId; ref->backupId = ptr.p->backupId;
ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail; ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
ref->signalNo = ptr.p->masterData.startBackup.signalNo;
gsn= GSN_START_BACKUP_REF; gsn= GSN_START_BACKUP_REF;
len= StartBackupRef::SignalLength; len= StartBackupRef::SignalLength;
pos= &ref->nodeId - signal->getDataPtr(); pos= &ref->nodeId - signal->getDataPtr();
...@@ -928,9 +921,7 @@ Backup::execBACKUP_REQ(Signal* signal) ...@@ -928,9 +921,7 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->backupKey[1] = 0; ptr.p->backupKey[1] = 0;
ptr.p->backupDataLen = 0; ptr.p->backupDataLen = 0;
ptr.p->masterData.errorCode = 0; ptr.p->masterData.errorCode = 0;
ptr.p->masterData.dropTrig.tableId = RNIL;
ptr.p->masterData.alterTrig.tableId = RNIL;
UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend(); UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ; ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ;
...@@ -1241,13 +1232,18 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) ...@@ -1241,13 +1232,18 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
signal->theData[2] = ptr.p->backupId; signal->theData[2] = ptr.p->backupId;
ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3); ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
/** /**
* Prepare Trig * We've received GSN_DEFINE_BACKUP_CONF from all participants.
*
* Our next step is to send START_BACKUP_REQ to all participants,
* who will then send CREATE_TRIG_REQ for all tables to their local
* DBTUP.
*/ */
TablePtr tabPtr; TablePtr tabPtr;
ndbrequire(ptr.p->tables.first(tabPtr)); ptr.p->tables.first(tabPtr);
sendCreateTrig(signal, ptr, tabPtr);
sendStartBackup(signal, ptr, tabPtr);
} }
/***************************************************************************** /*****************************************************************************
...@@ -1275,43 +1271,72 @@ Backup::sendCreateTrig(Signal* signal, ...@@ -1275,43 +1271,72 @@ Backup::sendCreateTrig(Signal* signal,
BackupRecordPtr ptr, TablePtr tabPtr) BackupRecordPtr ptr, TablePtr tabPtr)
{ {
CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend(); CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend();
ptr.p->masterData.gsn = GSN_CREATE_TRIG_REQ; /*
ptr.p->masterData.sendCounter = 3; * First, setup the structures
ptr.p->masterData.createTrig.tableId = tabPtr.p->tableId; */
for(Uint32 j=0; j<3; j++) {
jam();
TriggerPtr trigPtr;
if(!ptr.p->triggers.seize(trigPtr)) {
jam();
ptr.p->m_gsn = GSN_START_BACKUP_REF;
StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
ref->backupPtr = ptr.i;
ref->backupId = ptr.p->backupId;
ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
ref->nodeId = getOwnNodeId();
sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
StartBackupRef::SignalLength, JBB);
return;
} // if
const Uint32 triggerId= trigPtr.i;
tabPtr.p->triggerIds[j] = triggerId;
tabPtr.p->triggerAllocated[j] = true;
trigPtr.p->backupPtr = ptr.i;
trigPtr.p->tableId = tabPtr.p->tableId;
trigPtr.p->tab_ptr_i = tabPtr.i;
trigPtr.p->logEntry = 0;
trigPtr.p->event = j;
trigPtr.p->maxRecordSize = 2048;
trigPtr.p->operation =
&ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
trigPtr.p->operation->noOfBytes = 0;
trigPtr.p->operation->noOfRecords = 0;
trigPtr.p->errorCode = 0;
} // for
/*
* now ask DBTUP to create
*/
ptr.p->slaveData.gsn = GSN_CREATE_TRIG_REQ;
ptr.p->slaveData.trigSendCounter = 3;
ptr.p->slaveData.createTrig.tableId = tabPtr.p->tableId;
req->setUserRef(reference()); req->setUserRef(reference());
req->setReceiverRef(reference());
req->setConnectionPtr(ptr.i); req->setConnectionPtr(ptr.i);
req->setRequestType(CreateTrigReq::RT_USER); req->setRequestType(CreateTrigReq::RT_USER);
Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask; Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask;
createAttributeMask(tabPtr, attrMask); createAttributeMask(tabPtr, attrMask);
req->setAttributeMask(attrMask); req->setAttributeMask(attrMask);
req->setTableId(tabPtr.p->tableId); req->setTableId(tabPtr.p->tableId);
req->setIndexId(RNIL); // not used req->setIndexId(RNIL); // not used
req->setTriggerId(RNIL); // to be created
req->setTriggerType(TriggerType::SUBSCRIPTION); req->setTriggerType(TriggerType::SUBSCRIPTION);
req->setTriggerActionTime(TriggerActionTime::TA_DETACHED); req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
req->setMonitorReplicas(true); req->setMonitorReplicas(true);
req->setMonitorAllAttributes(false); req->setMonitorAllAttributes(false);
req->setOnline(false); // leave trigger offline req->setOnline(true);
char triggerName[MAX_TAB_NAME_SIZE];
Uint32 nameBuffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
LinearWriter w(nameBuffer, sizeof(nameBuffer) >> 2);
LinearSectionPtr lsPtr[3];
for (int i=0; i < 3; i++) { for (int i=0; i < 3; i++) {
req->setTriggerId(tabPtr.p->triggerIds[i]);
req->setTriggerEvent(triggerEventValues[i]); req->setTriggerEvent(triggerEventValues[i]);
req->setReportAllMonitoredAttributes(false);
BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i], sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
ptr.p->backupId, tabPtr.p->tableId); signal, CreateTrigReq::SignalLength, JBB);
w.reset();
w.add(CreateTrigReq::TriggerNameKey, triggerName);
lsPtr[0].p = nameBuffer;
lsPtr[0].sz = w.getWordsUsed();
sendSignal(DBDICT_REF, GSN_CREATE_TRIG_REQ,
signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
} }
} }
...@@ -1331,25 +1356,25 @@ Backup::execCREATE_TRIG_CONF(Signal* signal) ...@@ -1331,25 +1356,25 @@ Backup::execCREATE_TRIG_CONF(Signal* signal)
/** /**
* Verify that I'm waiting for this conf * Verify that I'm waiting for this conf
*
* ptr.p->masterRef != reference()
* as slaves and masters have triggers now.
*/ */
ndbrequire(ptr.p->masterRef == reference()); ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
ndbrequire(ptr.p->masterData.gsn == GSN_CREATE_TRIG_REQ); ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
ndbrequire(ptr.p->masterData.sendCounter.done() == false); ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
ndbrequire(ptr.p->masterData.createTrig.tableId == tableId);
TablePtr tabPtr; TablePtr tabPtr;
ndbrequire(findTable(ptr, tabPtr, tableId)); ndbrequire(findTable(ptr, tabPtr, tableId));
ndbrequire(type < 3); // if some decides to change the enums ndbrequire(type < 3); // if some decides to change the enums
ndbrequire(tabPtr.p->triggerIds[type] == ILLEGAL_TRIGGER_ID);
tabPtr.p->triggerIds[type] = triggerId;
createTrigReply(signal, ptr); createTrigReply(signal, ptr);
} }
void void
Backup::execCREATE_TRIG_REF(Signal* signal) Backup::execCREATE_TRIG_REF(Signal* signal)
{ {
jamEntry();
CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr(); CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr();
const Uint32 ptrI = ref->getConnectionPtr(); const Uint32 ptrI = ref->getConnectionPtr();
...@@ -1360,14 +1385,16 @@ Backup::execCREATE_TRIG_REF(Signal* signal) ...@@ -1360,14 +1385,16 @@ Backup::execCREATE_TRIG_REF(Signal* signal)
/** /**
* Verify that I'm waiting for this ref * Verify that I'm waiting for this ref
*
* ptr.p->masterRef != reference()
* as slaves and masters have triggers now
*/ */
ndbrequire(ptr.p->masterRef == reference()); ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
ndbrequire(ptr.p->masterData.gsn == GSN_CREATE_TRIG_REQ); ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
ndbrequire(ptr.p->masterData.sendCounter.done() == false); ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
ndbrequire(ptr.p->masterData.createTrig.tableId == tableId);
ptr.p->setErrorCode(ref->getErrorCode()); ptr.p->setErrorCode(ref->getErrorCode());
createTrigReply(signal, ptr); createTrigReply(signal, ptr);
} }
...@@ -1379,26 +1406,33 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr) ...@@ -1379,26 +1406,33 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
/** /**
* Check finished with table * Check finished with table
*/ */
ptr.p->masterData.sendCounter--; ptr.p->slaveData.trigSendCounter--;
if(ptr.p->masterData.sendCounter.done() == false){ if(ptr.p->slaveData.trigSendCounter.done() == false){
jam(); jam();
return; return;
}//if }//if
if (ERROR_INSERTED(10025)) if (ERROR_INSERTED(10025))
{ {
ptr.p->errorCode = 325; ptr.p->errorCode = 325;
} }
if(ptr.p->checkError()) { if(ptr.p->checkError()) {
jam(); jam();
masterAbort(signal, ptr); ptr.p->m_gsn = GSN_START_BACKUP_REF;
StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
ref->backupPtr = ptr.i;
ref->backupId = ptr.p->backupId;
ref->errorCode = ptr.p->errorCode;
ref->nodeId = getOwnNodeId();
sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
StartBackupRef::SignalLength, JBB);
return; return;
}//if }//if
TablePtr tabPtr; TablePtr tabPtr;
ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.createTrig.tableId)); ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.createTrig.tableId));
/** /**
* Next table * Next table
*/ */
...@@ -1410,14 +1444,16 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr) ...@@ -1410,14 +1444,16 @@ Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
}//if }//if
/** /**
* Finished with all tables, send StartBackupReq * We've finished creating triggers.
*
* send conf and wait
*/ */
ptr.p->tables.first(tabPtr); ptr.p->m_gsn = GSN_START_BACKUP_CONF;
ptr.p->masterData.startBackup.signalNo = 0; StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend();
ptr.p->masterData.startBackup.noOfSignals = conf->backupPtr = ptr.i;
(ptr.p->tables.noOfElements() + StartBackupReq::MaxTableTriggers - 1) / conf->backupId = ptr.p->backupId;
StartBackupReq::MaxTableTriggers; sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal,
sendStartBackup(signal, ptr, tabPtr); StartBackupConf::SignalLength, JBB);
} }
/***************************************************************************** /*****************************************************************************
...@@ -1430,33 +1466,23 @@ Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr) ...@@ -1430,33 +1466,23 @@ Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
{ {
ptr.p->masterData.startBackup.tablePtr = tabPtr.i; ptr.p->masterData.startBackup.tablePtr = tabPtr.i;
StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend(); StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend();
req->backupId = ptr.p->backupId; req->backupId = ptr.p->backupId;
req->backupPtr = ptr.i; req->backupPtr = ptr.i;
req->signalNo = ptr.p->masterData.startBackup.signalNo;
req->noOfSignals = ptr.p->masterData.startBackup.noOfSignals;
Uint32 i;
for(i = 0; i<StartBackupReq::MaxTableTriggers; i++) {
jam();
req->tableTriggers[i].tableId = tabPtr.p->tableId;
req->tableTriggers[i].triggerIds[0] = tabPtr.p->triggerIds[0];
req->tableTriggers[i].triggerIds[1] = tabPtr.p->triggerIds[1];
req->tableTriggers[i].triggerIds[2] = tabPtr.p->triggerIds[2];
if(!ptr.p->tables.next(tabPtr)){
jam();
i++;
break;
}//if
}//for
req->noOfTableTriggers = i;
/**
* We use trigger Ids that are unique to BACKUP.
* These don't interfere with other triggers (e.g. from DBDICT)
* as there is a special case in DBTUP.
*
* Consequently, backups during online upgrade won't work
*/
ptr.p->masterData.gsn = GSN_START_BACKUP_REQ; ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
ptr.p->masterData.sendCounter = ptr.p->nodes; ptr.p->masterData.sendCounter = ptr.p->nodes;
NodeReceiverGroup rg(BACKUP, ptr.p->nodes); NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
sendSignal(rg, GSN_START_BACKUP_REQ, signal, sendSignal(rg, GSN_START_BACKUP_REQ, signal,
StartBackupReq::HeaderLength + StartBackupReq::SignalLength, JBB);
(i * StartBackupReq::TableTriggerLength), JBB);
} }
void void
...@@ -1467,14 +1493,13 @@ Backup::execSTART_BACKUP_REF(Signal* signal) ...@@ -1467,14 +1493,13 @@ Backup::execSTART_BACKUP_REF(Signal* signal)
StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr(); StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr();
const Uint32 ptrI = ref->backupPtr; const Uint32 ptrI = ref->backupPtr;
//const Uint32 backupId = ref->backupId; //const Uint32 backupId = ref->backupId;
const Uint32 signalNo = ref->signalNo;
const Uint32 nodeId = ref->nodeId; const Uint32 nodeId = ref->nodeId;
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI); c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->errorCode); ptr.p->setErrorCode(ref->errorCode);
startBackupReply(signal, ptr, nodeId, signalNo); startBackupReply(signal, ptr, nodeId);
} }
void void
...@@ -1485,23 +1510,20 @@ Backup::execSTART_BACKUP_CONF(Signal* signal) ...@@ -1485,23 +1510,20 @@ Backup::execSTART_BACKUP_CONF(Signal* signal)
StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr(); StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr();
const Uint32 ptrI = conf->backupPtr; const Uint32 ptrI = conf->backupPtr;
//const Uint32 backupId = conf->backupId; //const Uint32 backupId = conf->backupId;
const Uint32 signalNo = conf->signalNo;
const Uint32 nodeId = refToNode(signal->senderBlockRef()); const Uint32 nodeId = refToNode(signal->senderBlockRef());
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI); c_backupPool.getPtr(ptr, ptrI);
startBackupReply(signal, ptr, nodeId, signalNo); startBackupReply(signal, ptr, nodeId);
} }
void void
Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
Uint32 nodeId, Uint32 signalNo)
{ {
CRASH_INSERTION((10004)); CRASH_INSERTION((10004));
ndbrequire(ptr.p->masterData.startBackup.signalNo == signalNo);
if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) { if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) {
jam(); jam();
return; return;
...@@ -1518,148 +1540,20 @@ Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, ...@@ -1518,148 +1540,20 @@ Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr,
return; return;
} }
TablePtr tabPtr;
c_tablePool.getPtr(tabPtr, ptr.p->masterData.startBackup.tablePtr);
for(Uint32 i = 0; i<StartBackupReq::MaxTableTriggers; i++) {
jam();
if(!ptr.p->tables.next(tabPtr)) {
jam();
break;
}//if
}//for
if(tabPtr.i != RNIL) {
jam();
ptr.p->masterData.startBackup.signalNo++;
sendStartBackup(signal, ptr, tabPtr);
return;
}
sendAlterTrig(signal, ptr);
}
/*****************************************************************************
*
* Master functionallity - Activate triggers
*
*****************************************************************************/
void
Backup::sendAlterTrig(Signal* signal, BackupRecordPtr ptr)
{
AlterTrigReq * req =(AlterTrigReq *)signal->getDataPtrSend();
ptr.p->masterData.gsn = GSN_ALTER_TRIG_REQ;
ptr.p->masterData.sendCounter = 0;
req->setUserRef(reference());
req->setConnectionPtr(ptr.i);
req->setRequestType(AlterTrigReq::RT_USER);
req->setTriggerInfo(0); // not used on ALTER via DICT
req->setOnline(true);
req->setReceiverRef(reference());
TablePtr tabPtr;
if (ptr.p->masterData.alterTrig.tableId == RNIL) {
jam();
ptr.p->tables.first(tabPtr);
} else {
jam();
ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.alterTrig.tableId));
ptr.p->tables.next(tabPtr);
}//if
if (tabPtr.i != RNIL) {
jam();
ptr.p->masterData.alterTrig.tableId = tabPtr.p->tableId;
req->setTableId(tabPtr.p->tableId);
req->setTriggerId(tabPtr.p->triggerIds[0]);
sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ,
signal, AlterTrigReq::SignalLength, JBB);
req->setTriggerId(tabPtr.p->triggerIds[1]);
sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ,
signal, AlterTrigReq::SignalLength, JBB);
req->setTriggerId(tabPtr.p->triggerIds[2]);
sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ,
signal, AlterTrigReq::SignalLength, JBB);
ptr.p->masterData.sendCounter += 3;
return;
}//if
ptr.p->masterData.alterTrig.tableId = RNIL;
/** /**
* Finished with all tables * Wait for GCP
*/ */
ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ; ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
ptr.p->masterData.waitGCP.startBackup = true; ptr.p->masterData.waitGCP.startBackup = true;
WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend(); WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend();
waitGCPReq->senderRef = reference(); waitGCPReq->senderRef = reference();
waitGCPReq->senderData = ptr.i; waitGCPReq->senderData = ptr.i;
waitGCPReq->requestType = WaitGCPReq::CompleteForceStart; waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
WaitGCPReq::SignalLength,JBB); WaitGCPReq::SignalLength,JBB);
} }
void
Backup::execALTER_TRIG_CONF(Signal* signal)
{
jamEntry();
AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtr();
const Uint32 ptrI = conf->getConnectionPtr();
BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI);
alterTrigReply(signal, ptr);
}
void
Backup::execALTER_TRIG_REF(Signal* signal)
{
jamEntry();
AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtr();
const Uint32 ptrI = ref->getConnectionPtr();
BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->getErrorCode());
alterTrigReply(signal, ptr);
}
void
Backup::alterTrigReply(Signal* signal, BackupRecordPtr ptr)
{
CRASH_INSERTION((10005));
ndbrequire(ptr.p->masterRef == reference());
ndbrequire(ptr.p->masterData.gsn == GSN_ALTER_TRIG_REQ);
ndbrequire(ptr.p->masterData.sendCounter.done() == false);
ptr.p->masterData.sendCounter--;
if(ptr.p->masterData.sendCounter.done() == false){
jam();
return;
}//if
if(ptr.p->checkError()){
jam();
masterAbort(signal, ptr);
return;
}//if
sendAlterTrig(signal, ptr);
}
void void
Backup::execWAIT_GCP_REF(Signal* signal) Backup::execWAIT_GCP_REF(Signal* signal)
{ {
...@@ -1720,7 +1614,12 @@ Backup::execWAIT_GCP_CONF(Signal* signal){ ...@@ -1720,7 +1614,12 @@ Backup::execWAIT_GCP_CONF(Signal* signal){
{ {
CRASH_INSERTION((10009)); CRASH_INSERTION((10009));
ptr.p->stopGCP = gcp; ptr.p->stopGCP = gcp;
sendDropTrig(signal, ptr); // regular dropping of triggers /**
* Backup is complete - begin cleanup
* STOP_BACKUP_REQ is sent to participants.
* They then drop the local triggers
*/
sendStopBackup(signal, ptr);
return; return;
}//if }//if
...@@ -1927,8 +1826,8 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal) ...@@ -1927,8 +1826,8 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
} }
/***************************************************************************** /*****************************************************************************
* *
* Master functionallity - Drop triggers * Slave functionallity - Drop triggers
* *
*****************************************************************************/ *****************************************************************************/
...@@ -1936,23 +1835,63 @@ void ...@@ -1936,23 +1835,63 @@ void
Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr) Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr)
{ {
TablePtr tabPtr; TablePtr tabPtr;
if (ptr.p->masterData.dropTrig.tableId == RNIL) { ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
if (ptr.p->slaveData.dropTrig.tableId == RNIL) {
jam(); jam();
ptr.p->tables.first(tabPtr); ptr.p->tables.first(tabPtr);
} else { } else {
jam(); jam();
ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.dropTrig.tableId)); ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.dropTrig.tableId));
ptr.p->tables.next(tabPtr); ptr.p->tables.next(tabPtr);
}//if }//if
if (tabPtr.i != RNIL) { if (tabPtr.i != RNIL) {
jam(); jam();
sendDropTrig(signal, ptr, tabPtr); sendDropTrig(signal, ptr, tabPtr);
} else { } else {
jam(); /**
ptr.p->masterData.dropTrig.tableId = RNIL; * Insert footers
*/
{
BackupFilePtr filePtr;
ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
Uint32 * dst;
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
* dst = 0;
filePtr.p->operation.dataBuffer.updateWritePtr(1);
}
sendStopBackup(signal, ptr); {
}//if BackupFilePtr filePtr;
ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
Uint32 * dst;
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
BackupFormat::CtlFile::GCPEntry * gcp =
(BackupFormat::CtlFile::GCPEntry*)dst;
gcp->SectionType = htonl(BackupFormat::GCP_ENTRY);
gcp->SectionLength = htonl(gcpSz);
gcp->StartGCP = htonl(ptr.p->startGCP);
gcp->StopGCP = htonl(ptr.p->stopGCP - 1);
filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
}
{ // UNLOCK while dropping trigger for better timeslicing
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);
}
} }
void void
...@@ -1961,40 +1900,26 @@ Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr) ...@@ -1961,40 +1900,26 @@ Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
jam(); jam();
DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend(); DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend();
ptr.p->masterData.gsn = GSN_DROP_TRIG_REQ; ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
ptr.p->masterData.sendCounter = 0; ptr.p->slaveData.trigSendCounter = 0;
req->setConnectionPtr(ptr.i); req->setConnectionPtr(ptr.i);
req->setUserRef(reference()); // Sending to myself req->setUserRef(reference()); // Sending to myself
req->setRequestType(DropTrigReq::RT_USER); req->setRequestType(DropTrigReq::RT_USER);
req->setIndexId(RNIL); req->setIndexId(RNIL);
req->setTriggerInfo(0); // not used on DROP via DICT req->setTriggerInfo(0); // not used on DROP
req->setTriggerType(TriggerType::SUBSCRIPTION);
req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
char triggerName[MAX_TAB_NAME_SIZE]; ptr.p->slaveData.dropTrig.tableId = tabPtr.p->tableId;
Uint32 nameBuffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
LinearWriter w(nameBuffer, sizeof(nameBuffer) >> 2);
LinearSectionPtr lsPtr[3];
ptr.p->masterData.dropTrig.tableId = tabPtr.p->tableId;
req->setTableId(tabPtr.p->tableId); req->setTableId(tabPtr.p->tableId);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Uint32 id = tabPtr.p->triggerIds[i]; Uint32 id = tabPtr.p->triggerIds[i];
req->setTriggerId(id); req->setTriggerId(id);
if (id != ILLEGAL_TRIGGER_ID) { req->setTriggerEvent(triggerEventValues[i]);
sendSignal(DBDICT_REF, GSN_DROP_TRIG_REQ, sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB); signal, DropTrigReq::SignalLength, JBB);
} else { ptr.p->slaveData.trigSendCounter ++;
BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
ptr.p->backupId, tabPtr.p->tableId);
w.reset();
w.add(CreateTrigReq::TriggerNameKey, triggerName);
lsPtr[0].p = nameBuffer;
lsPtr[0].sz = w.getWordsUsed();
sendSignal(DBDICT_REF, GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB, lsPtr, 1);
}
ptr.p->masterData.sendCounter ++;
} }
} }
...@@ -2005,11 +1930,13 @@ Backup::execDROP_TRIG_REF(Signal* signal) ...@@ -2005,11 +1930,13 @@ Backup::execDROP_TRIG_REF(Signal* signal)
DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr(); DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
const Uint32 ptrI = ref->getConnectionPtr(); const Uint32 ptrI = ref->getConnectionPtr();
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI); c_backupPool.getPtr(ptr, ptrI);
//ndbrequire(ref->getErrorCode() == DropTrigRef::NoSuchTrigger); ndbout << "ERROR DROPPING TRIGGER: " << ref->getConf()->getTriggerId();
ndbout << " Err: " << (Uint32)ref->getErrorCode() << endl << endl;
dropTrigReply(signal, ptr); dropTrigReply(signal, ptr);
} }
...@@ -2020,29 +1947,29 @@ Backup::execDROP_TRIG_CONF(Signal* signal) ...@@ -2020,29 +1947,29 @@ Backup::execDROP_TRIG_CONF(Signal* signal)
DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr(); DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
const Uint32 ptrI = conf->getConnectionPtr(); const Uint32 ptrI = conf->getConnectionPtr();
const Uint32 triggerId= conf->getTriggerId();
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI); c_backupPool.getPtr(ptr, ptrI);
dropTrigReply(signal, ptr); dropTrigReply(signal, ptr);
} }
void void
Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr) Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr)
{ {
CRASH_INSERTION((10012)); CRASH_INSERTION((10012));
ndbrequire(ptr.p->masterRef == reference()); ndbrequire(ptr.p->slaveData.gsn == GSN_DROP_TRIG_REQ);
ndbrequire(ptr.p->masterData.gsn == GSN_DROP_TRIG_REQ); ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
ndbrequire(ptr.p->masterData.sendCounter.done() == false);
// move from .masterData to .slaveData
ptr.p->masterData.sendCounter--; ptr.p->slaveData.trigSendCounter--;
if(ptr.p->masterData.sendCounter.done() == false){ if(ptr.p->slaveData.trigSendCounter.done() == false){
jam(); jam();
return; return;
}//if }//if
sendDropTrig(signal, ptr); // recursive next sendDropTrig(signal, ptr); // recursive next
} }
...@@ -2165,6 +2092,9 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr) ...@@ -2165,6 +2092,9 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
#ifdef DEBUG_ABORT #ifdef DEBUG_ABORT
ndbout_c("************ masterAbort"); ndbout_c("************ masterAbort");
#endif #endif
ndbassert(ptr.p->masterRef == reference());
if(ptr.p->masterData.errorCode != 0) if(ptr.p->masterData.errorCode != 0)
{ {
jam(); jam();
...@@ -2208,13 +2138,13 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr) ...@@ -2208,13 +2138,13 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
case GSN_BACKUP_FRAGMENT_REQ: case GSN_BACKUP_FRAGMENT_REQ:
jam(); jam();
ptr.p->stopGCP= ptr.p->startGCP + 1; ptr.p->stopGCP= ptr.p->startGCP + 1;
sendDropTrig(signal, ptr); // dropping due to error sendStopBackup(signal, ptr); // dropping due to error
return; return;
case GSN_UTIL_SEQUENCE_REQ: case GSN_UTIL_SEQUENCE_REQ:
case GSN_UTIL_LOCK_REQ: case GSN_UTIL_LOCK_REQ:
case GSN_DROP_TRIG_REQ:
ndbrequire(false); ndbrequire(false);
return; return;
case GSN_DROP_TRIG_REQ:
case GSN_STOP_BACKUP_REQ: case GSN_STOP_BACKUP_REQ:
return; return;
} }
...@@ -2329,6 +2259,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) ...@@ -2329,6 +2259,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ; ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ;
ptr.p->slaveState.forceState(INITIAL); ptr.p->slaveState.forceState(INITIAL);
ptr.p->slaveState.setState(DEFINING); ptr.p->slaveState.setState(DEFINING);
ptr.p->slaveData.dropTrig.tableId = RNIL;
ptr.p->errorCode = 0; ptr.p->errorCode = 0;
ptr.p->clientRef = req->clientRef; ptr.p->clientRef = req->clientRef;
ptr.p->clientData = req->clientData; ptr.p->clientData = req->clientData;
...@@ -2345,14 +2276,14 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) ...@@ -2345,14 +2276,14 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->backupKey[0] = req->backupKey[0]; ptr.p->backupKey[0] = req->backupKey[0];
ptr.p->backupKey[1] = req->backupKey[1]; ptr.p->backupKey[1] = req->backupKey[1];
ptr.p->backupDataLen = req->backupDataLen; ptr.p->backupDataLen = req->backupDataLen;
ptr.p->masterData.dropTrig.tableId = RNIL;
ptr.p->masterData.alterTrig.tableId = RNIL;
ptr.p->masterData.errorCode = 0; ptr.p->masterData.errorCode = 0;
ptr.p->noOfBytes = 0; ptr.p->noOfBytes = 0;
ptr.p->noOfRecords = 0; ptr.p->noOfRecords = 0;
ptr.p->noOfLogBytes = 0; ptr.p->noOfLogBytes = 0;
ptr.p->noOfLogRecords = 0; ptr.p->noOfLogRecords = 0;
ptr.p->currGCP = 0; ptr.p->currGCP = 0;
ptr.p->startGCP = 0;
ptr.p->stopGCP = 0;
/** /**
* Allocate files * Allocate files
...@@ -3261,63 +3192,22 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) ...@@ -3261,63 +3192,22 @@ Backup::execSTART_BACKUP_REQ(Signal* signal)
jamEntry(); jamEntry();
CRASH_INSERTION((10015)); CRASH_INSERTION((10015));
StartBackupReq* req = (StartBackupReq*)signal->getDataPtr(); StartBackupReq* req = (StartBackupReq*)signal->getDataPtr();
const Uint32 ptrI = req->backupPtr; const Uint32 ptrI = req->backupPtr;
//const Uint32 backupId = req->backupId;
const Uint32 signalNo = req->signalNo;
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI); c_backupPool.getPtr(ptr, ptrI);
ptr.p->slaveState.setState(STARTED); ptr.p->slaveState.setState(STARTED);
ptr.p->m_gsn = GSN_START_BACKUP_REQ; ptr.p->m_gsn = GSN_START_BACKUP_REQ;
for(Uint32 i = 0; i<req->noOfTableTriggers; i++) {
jam();
TablePtr tabPtr;
ndbrequire(findTable(ptr, tabPtr, req->tableTriggers[i].tableId));
for(Uint32 j = 0; j<3; j++) {
jam();
const Uint32 triggerId = req->tableTriggers[i].triggerIds[j];
tabPtr.p->triggerIds[j] = triggerId;
TriggerPtr trigPtr;
if(!ptr.p->triggers.seizeId(trigPtr, triggerId)) {
jam();
ptr.p->m_gsn = GSN_START_BACKUP_REF;
StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
ref->backupPtr = ptr.i;
ref->backupId = ptr.p->backupId;
ref->signalNo = signalNo;
ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
ref->nodeId = getOwnNodeId();
sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
StartBackupRef::SignalLength, JBB);
return;
}//if
tabPtr.p->triggerAllocated[j] = true;
trigPtr.p->backupPtr = ptr.i;
trigPtr.p->tableId = tabPtr.p->tableId;
trigPtr.p->tab_ptr_i = tabPtr.i;
trigPtr.p->logEntry = 0;
trigPtr.p->event = j;
trigPtr.p->maxRecordSize = 2048;
trigPtr.p->operation =
&ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
trigPtr.p->operation->noOfBytes = 0;
trigPtr.p->operation->noOfRecords = 0;
trigPtr.p->errorCode = 0;
}//for
}//for
/** /**
* Start file threads... * Start file threads...
*/ */
BackupFilePtr filePtr; BackupFilePtr filePtr;
for(ptr.p->files.first(filePtr); for(ptr.p->files.first(filePtr);
filePtr.i!=RNIL; filePtr.i!=RNIL;
ptr.p->files.next(filePtr)){ ptr.p->files.next(filePtr)){
jam(); jam();
if(filePtr.p->fileRunning == 0) { if(filePtr.p->fileRunning == 0) {
...@@ -3328,14 +3218,13 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) ...@@ -3328,14 +3218,13 @@ Backup::execSTART_BACKUP_REQ(Signal* signal)
sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2); sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
}//if }//if
}//for }//for
ptr.p->m_gsn = GSN_START_BACKUP_CONF; /**
StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend(); * Tell DBTUP to create triggers
conf->backupPtr = ptr.i; */
conf->backupId = ptr.p->backupId; TablePtr tabPtr;
conf->signalNo = signalNo; ndbrequire(ptr.p->tables.first(tabPtr));
sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal, sendCreateTrig(signal, ptr, tabPtr);
StartBackupConf::SignalLength, JBB);
} }
/***************************************************************************** /*****************************************************************************
...@@ -3887,7 +3776,7 @@ void ...@@ -3887,7 +3776,7 @@ void
Backup::execFSAPPENDCONF(Signal* signal) Backup::execFSAPPENDCONF(Signal* signal)
{ {
jamEntry(); jamEntry();
CRASH_INSERTION((10018)); CRASH_INSERTION((10018));
//FsConf * conf = (FsConf*)signal->getDataPtr(); //FsConf * conf = (FsConf*)signal->getDataPtr();
...@@ -3990,10 +3879,13 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal) ...@@ -3990,10 +3879,13 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal)
Uint32 result; Uint32 result;
jamEntry(); jamEntry();
c_triggerPool.getPtr(trigPtr, trigger_id); c_triggerPool.getPtr(trigPtr, trigger_id);
c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i); c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
tabPtr.p->fragments.getPtr(fragPtr, frag_id); tabPtr.p->fragments.getPtr(fragPtr, frag_id);
if (fragPtr.p->node != getOwnNodeId()) { if (fragPtr.p->node != getOwnNodeId()) {
jam(); jam();
result = ZFALSE; result = ZFALSE;
} else { } else {
...@@ -4014,12 +3906,12 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { ...@@ -4014,12 +3906,12 @@ Backup::execTRIG_ATTRINFO(Signal* signal) {
TriggerPtr trigPtr; TriggerPtr trigPtr;
c_triggerPool.getPtr(trigPtr, trg->getTriggerId()); c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online... ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
if(trigPtr.p->errorCode != 0) { if(trigPtr.p->errorCode != 0) {
jam(); jam();
return; return;
}//if }//if
if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) { if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
jam(); jam();
/** /**
...@@ -4056,18 +3948,29 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { ...@@ -4056,18 +3948,29 @@ Backup::execTRIG_ATTRINFO(Signal* signal) {
memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength); memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength);
return; return;
}//if }//if
logEntry = (BackupFormat::LogFile::LogEntry *)dst; logEntry = (BackupFormat::LogFile::LogEntry *)dst;
trigPtr.p->logEntry = logEntry; trigPtr.p->logEntry = logEntry;
logEntry->Length = 0; logEntry->Length = 0;
logEntry->TableId = htonl(trigPtr.p->tableId); logEntry->TableId = htonl(trigPtr.p->tableId);
logEntry->TriggerEvent = htonl(trigPtr.p->event);
if(trigPtr.p->event==0)
logEntry->TriggerEvent= htonl(TriggerEvent::TE_INSERT);
else if(trigPtr.p->event==1)
logEntry->TriggerEvent= htonl(TriggerEvent::TE_UPDATE);
else if(trigPtr.p->event==2)
logEntry->TriggerEvent= htonl(TriggerEvent::TE_DELETE);
else {
ndbout << "Bad Event: " << trigPtr.p->event << endl;
ndbrequire(false);
}
} else { } else {
ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId)); ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId));
ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event)); // ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event));
}//if }//if
const Uint32 pos = logEntry->Length; const Uint32 pos = logEntry->Length;
const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength; const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2); memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2);
...@@ -4100,16 +4003,15 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) ...@@ -4100,16 +4003,15 @@ Backup::execFIRE_TRIG_ORD(Signal* signal)
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
if(gci != ptr.p->currGCP) if(gci != ptr.p->currGCP)
{ {
jam(); jam();
trigPtr.p->logEntry->TriggerEvent|= htonl(0x10000);
trigPtr.p->logEntry->TriggerEvent = htonl(trigPtr.p->event | 0x10000);
trigPtr.p->logEntry->Data[len] = htonl(gci); trigPtr.p->logEntry->Data[len] = htonl(gci);
len++; len++;
ptr.p->currGCP = gci; ptr.p->currGCP = gci;
}//if }
len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2; len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
trigPtr.p->logEntry->Length = htonl(len); trigPtr.p->logEntry->Length = htonl(len);
...@@ -4165,7 +4067,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) ...@@ -4165,7 +4067,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
* At least one GCP must have passed * At least one GCP must have passed
*/ */
ndbrequire(stopGCP > startGCP); ndbrequire(stopGCP > startGCP);
/** /**
* Get backup record * Get backup record
*/ */
...@@ -4174,50 +4076,13 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) ...@@ -4174,50 +4076,13 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
ptr.p->slaveState.setState(STOPPING); ptr.p->slaveState.setState(STOPPING);
ptr.p->m_gsn = GSN_STOP_BACKUP_REQ; ptr.p->m_gsn = GSN_STOP_BACKUP_REQ;
ptr.p->startGCP= startGCP;
ptr.p->stopGCP= stopGCP;
/** /**
* Insert footers * Destroy the triggers in local DBTUP we created
*/ */
{ sendDropTrig(signal, ptr);
BackupFilePtr filePtr;
ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
Uint32 * dst;
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
* dst = 0;
filePtr.p->operation.dataBuffer.updateWritePtr(1);
}
{
BackupFilePtr filePtr;
ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
Uint32 * dst;
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
BackupFormat::CtlFile::GCPEntry * gcp =
(BackupFormat::CtlFile::GCPEntry*)dst;
gcp->SectionType = htonl(BackupFormat::GCP_ENTRY);
gcp->SectionLength = htonl(gcpSz);
gcp->StartGCP = htonl(startGCP);
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);
} }
void void
...@@ -4483,19 +4348,10 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) ...@@ -4483,19 +4348,10 @@ Backup::execABORT_BACKUP_ORD(Signal* signal)
ptr.p->masterRef = reference(); ptr.p->masterRef = reference();
ptr.p->nodes.clear(); ptr.p->nodes.clear();
ptr.p->nodes.set(getOwnNodeId()); ptr.p->nodes.set(getOwnNodeId());
if(ref == reference())
{ ptr.p->stopGCP= ptr.p->startGCP + 1;
ptr.p->stopGCP= ptr.p->startGCP + 1; sendStopBackup(signal, ptr);
sendDropTrig(signal, ptr);
}
else
{
ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
ptr.p->masterData.sendCounter.clearWaitingFor();
ptr.p->masterData.sendCounter.setWaitingFor(getOwnNodeId());
closeFiles(signal, ptr);
}
} }
......
...@@ -96,8 +96,6 @@ protected: ...@@ -96,8 +96,6 @@ protected:
void execGET_TABINFO_CONF(Signal* signal); void execGET_TABINFO_CONF(Signal* signal);
void execCREATE_TRIG_REF(Signal* signal); void execCREATE_TRIG_REF(Signal* signal);
void execCREATE_TRIG_CONF(Signal* signal); void execCREATE_TRIG_CONF(Signal* signal);
void execALTER_TRIG_REF(Signal* signal);
void execALTER_TRIG_CONF(Signal* signal);
void execDROP_TRIG_REF(Signal* signal); void execDROP_TRIG_REF(Signal* signal);
void execDROP_TRIG_CONF(Signal* signal); void execDROP_TRIG_CONF(Signal* signal);
...@@ -426,6 +424,7 @@ public: ...@@ -426,6 +424,7 @@ public:
Uint32 clientRef; Uint32 clientRef;
Uint32 clientData; Uint32 clientData;
Uint32 flags; Uint32 flags;
Uint32 signalNo;
Uint32 backupId; Uint32 backupId;
Uint32 backupKey[2]; Uint32 backupKey[2];
Uint32 masterRef; Uint32 masterRef;
...@@ -451,7 +450,18 @@ public: ...@@ -451,7 +450,18 @@ public:
Uint32 backupDataLen; // Used for (un)packing backup request Uint32 backupDataLen; // Used for (un)packing backup request
Array<Page32> pages; // Used for (un)packing backup request Array<Page32> pages; // Used for (un)packing backup request
SimpleProperties props;// Used for (un)packing backup request SimpleProperties props;// Used for (un)packing backup request
struct SlaveData {
SignalCounter trigSendCounter;
Uint32 gsn;
struct {
Uint32 tableId;
} createTrig;
struct {
Uint32 tableId;
} dropTrig;
} slaveData;
struct MasterData { struct MasterData {
MasterData(Backup & b) MasterData(Backup & b)
{ {
...@@ -462,15 +472,6 @@ public: ...@@ -462,15 +472,6 @@ public:
Uint32 gsn; Uint32 gsn;
SignalCounter sendCounter; SignalCounter sendCounter;
Uint32 errorCode; Uint32 errorCode;
struct {
Uint32 tableId;
} createTrig;
struct {
Uint32 tableId;
} dropTrig;
struct {
Uint32 tableId;
} alterTrig;
union { union {
struct { struct {
Uint32 startBackup; Uint32 startBackup;
...@@ -563,7 +564,7 @@ public: ...@@ -563,7 +564,7 @@ public:
void defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId); void defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId);
void createTrigReply(Signal* signal, BackupRecordPtr ptr); void createTrigReply(Signal* signal, BackupRecordPtr ptr);
void alterTrigReply(Signal* signal, BackupRecordPtr ptr); void alterTrigReply(Signal* signal, BackupRecordPtr ptr);
void startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32, Uint32); void startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32);
void stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId); void stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId);
void defineBackupRef(Signal*, BackupRecordPtr, Uint32 errCode = 0); void defineBackupRef(Signal*, BackupRecordPtr, Uint32 errCode = 0);
......
...@@ -25,15 +25,12 @@ BACKUP_REQ ...@@ -25,15 +25,12 @@ BACKUP_REQ
<------------------------------- <-------------------------------
BACKUP_CONF BACKUP_CONF
<---------------- <----------------
CREATE_TRIG
--------------> (If master crashes here -> rouge triggers/memory leak)
<--------------
START_BACKUP START_BACKUP
------------------------------> ------------------------------>
CREATE_TRIG
-------------->
<--------------
<------------------------------ <------------------------------
ALTER_TRIG
-------------->
<--------------
WAIT_GCP WAIT_GCP
--------------> -------------->
<-------------- <--------------
...@@ -46,11 +43,11 @@ BACKUP_CONF ...@@ -46,11 +43,11 @@ BACKUP_CONF
WAIT_GCP WAIT_GCP
--------------> -------------->
<-------------- <--------------
DROP_TRIG
-------------->
<--------------
STOP_BACKUP STOP_BACKUP
------------------------------> ------------------------------>
DROP_TRIG
-------------->
<--------------
<------------------------------ <------------------------------
BACKUP_COMPLETE_REP BACKUP_COMPLETE_REP
<---------------- <----------------
......
...@@ -62,9 +62,6 @@ Backup::Backup(const Configuration & conf) : ...@@ -62,9 +62,6 @@ Backup::Backup(const Configuration & conf) :
addRecSignal(GSN_CREATE_TRIG_REF, &Backup::execCREATE_TRIG_REF); addRecSignal(GSN_CREATE_TRIG_REF, &Backup::execCREATE_TRIG_REF);
addRecSignal(GSN_CREATE_TRIG_CONF, &Backup::execCREATE_TRIG_CONF); addRecSignal(GSN_CREATE_TRIG_CONF, &Backup::execCREATE_TRIG_CONF);
addRecSignal(GSN_ALTER_TRIG_REF, &Backup::execALTER_TRIG_REF);
addRecSignal(GSN_ALTER_TRIG_CONF, &Backup::execALTER_TRIG_CONF);
addRecSignal(GSN_DROP_TRIG_REF, &Backup::execDROP_TRIG_REF); addRecSignal(GSN_DROP_TRIG_REF, &Backup::execDROP_TRIG_REF);
addRecSignal(GSN_DROP_TRIG_CONF, &Backup::execDROP_TRIG_CONF); addRecSignal(GSN_DROP_TRIG_CONF, &Backup::execDROP_TRIG_CONF);
......
...@@ -777,6 +777,10 @@ struct TupTriggerData { ...@@ -777,6 +777,10 @@ struct TupTriggerData {
/** /**
* Trigger id, used by DICT/TRIX to identify the trigger * Trigger id, used by DICT/TRIX to identify the trigger
*
* trigger Ids are unique per block for SUBSCRIPTION triggers.
* This is so that BACKUP can use TUP triggers directly and delete them
* properly.
*/ */
Uint32 triggerId; Uint32 triggerId;
...@@ -2012,7 +2016,9 @@ private: ...@@ -2012,7 +2016,9 @@ private:
bool createTrigger(Tablerec* table, const CreateTrigReq* req); bool createTrigger(Tablerec* table, const CreateTrigReq* req);
Uint32 dropTrigger(Tablerec* table, const DropTrigReq* req); Uint32 dropTrigger(Tablerec* table,
const DropTrigReq* req,
BlockNumber sender);
void void
checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct, checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
......
...@@ -186,7 +186,7 @@ Dbtup::execDROP_TRIG_REQ(Signal* signal) ...@@ -186,7 +186,7 @@ Dbtup::execDROP_TRIG_REQ(Signal* signal)
ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
// Drop trigger // Drop trigger
Uint32 r = dropTrigger(tabPtr.p, req); Uint32 r = dropTrigger(tabPtr.p, req, refToBlock(senderRef));
if (r == 0){ if (r == 0){
// Send conf // Send conf
DropTrigConf* const conf = (DropTrigConf*)signal->getDataPtrSend(); DropTrigConf* const conf = (DropTrigConf*)signal->getDataPtrSend();
...@@ -318,7 +318,7 @@ Dbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId) ...@@ -318,7 +318,7 @@ Dbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId)
/* */ /* */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
Uint32 Uint32
Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req) Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req, BlockNumber sender)
{ {
if (ERROR_INSERTED(4004)) { if (ERROR_INSERTED(4004)) {
CLEAR_ERROR_INSERT_VALUE; CLEAR_ERROR_INSERT_VALUE;
...@@ -330,7 +330,7 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req) ...@@ -330,7 +330,7 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req)
TriggerActionTime::Value ttime = req->getTriggerActionTime(); TriggerActionTime::Value ttime = req->getTriggerActionTime();
TriggerEvent::Value tevent = req->getTriggerEvent(); TriggerEvent::Value tevent = req->getTriggerEvent();
// ndbout_c("Drop TupTrigger %u = %u %u %u %u", triggerId, table, ttype, ttime, tevent); // ndbout_c("Drop TupTrigger %u = %u %u %u %u by %u", triggerId, table, ttype, ttime, tevent, sender);
ArrayList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent); ArrayList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent);
ndbrequire(tlist != NULL); ndbrequire(tlist != NULL);
...@@ -339,6 +339,19 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req) ...@@ -339,6 +339,19 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req)
for (tlist->first(ptr); !ptr.isNull(); tlist->next(ptr)) { for (tlist->first(ptr); !ptr.isNull(); tlist->next(ptr)) {
ljam(); ljam();
if (ptr.p->triggerId == triggerId) { if (ptr.p->triggerId == triggerId) {
if(ttype==TriggerType::SUBSCRIPTION && sender != ptr.p->m_receiverBlock)
{
/**
* You can only drop your own triggers for subscription triggers.
* Trigger IDs are private for each block.
*
* SUMA encodes information in the triggerId
*
* Backup doesn't really care about the Ids though.
*/
ljam();
continue;
}
ljam(); ljam();
tlist->release(ptr.i); tlist->release(ptr.i);
return 0; return 0;
......
...@@ -193,7 +193,7 @@ runDDL(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -193,7 +193,7 @@ runDDL(NDBT_Context* ctx, NDBT_Step* step){
} }
int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){ int runDropTablesRestart(NDBT_Context* ctx, NDBT_Step* step){
NdbRestarter restarter; NdbRestarter restarter;
Ndb* pNdb = GETNDB(step); Ndb* pNdb = GETNDB(step);
...@@ -201,7 +201,7 @@ int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -201,7 +201,7 @@ int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table *tab = ctx->getTab(); const NdbDictionary::Table *tab = ctx->getTab();
pNdb->getDictionary()->dropTable(tab->getName()); pNdb->getDictionary()->dropTable(tab->getName());
if (restarter.restartAll(true) != 0) if (restarter.restartAll(false) != 0)
return NDBT_FAILED; return NDBT_FAILED;
if (restarter.waitClusterStarted() != 0) if (restarter.waitClusterStarted() != 0)
...@@ -406,6 +406,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -406,6 +406,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
// TEMPORARY FIX // TEMPORARY FIX
// To erase all tables from cache(s) // To erase all tables from cache(s)
// To be removed, maybe replaced by ndb.invalidate(); // To be removed, maybe replaced by ndb.invalidate();
runDropTable(ctx,step);
{ {
Bank bank(ctx->m_cluster_connection); Bank bank(ctx->m_cluster_connection);
...@@ -416,8 +417,8 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -416,8 +417,8 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
} }
// END TEMPORARY FIX // END TEMPORARY FIX
ndbout << "Performing initial restart" << endl; ndbout << "Performing restart" << endl;
if (restarter.restartAll(true) != 0) if (restarter.restartAll(false) != 0)
return NDBT_FAILED; return NDBT_FAILED;
if (restarter.waitClusterStarted() != 0) if (restarter.waitClusterStarted() != 0)
...@@ -465,12 +466,12 @@ TESTCASE("BackupOne", ...@@ -465,12 +466,12 @@ TESTCASE("BackupOne",
"Test that backup and restore works on one table \n" "Test that backup and restore works on one table \n"
"1. Load table\n" "1. Load table\n"
"2. Backup\n" "2. Backup\n"
"3. Restart -i\n" "3. Drop tables and restart \n"
"4. Restore\n" "4. Restore\n"
"5. Verify count and content of table\n"){ "5. Verify count and content of table\n"){
INITIALIZER(runLoadTable); INITIALIZER(runLoadTable);
INITIALIZER(runBackupOne); INITIALIZER(runBackupOne);
INITIALIZER(runRestartInitial); INITIALIZER(runDropTablesRestart);
INITIALIZER(runRestoreOne); INITIALIZER(runRestoreOne);
VERIFIER(runVerifyOne); VERIFIER(runVerifyOne);
FINALIZER(runClearTable); FINALIZER(runClearTable);
......
...@@ -199,7 +199,6 @@ int ...@@ -199,7 +199,6 @@ int
NFDuringBackupM_codes[] = { NFDuringBackupM_codes[] = {
10003, 10003,
10004, 10004,
10005,
10007, 10007,
10008, 10008,
10009, 10009,
...@@ -349,6 +348,7 @@ NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz, ...@@ -349,6 +348,7 @@ NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz,
int int
FailS_codes[] = { FailS_codes[] = {
10025,
10027, 10027,
10033 10033
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment