Backup.cpp

Go to the documentation of this file.
00001 /* Copyright (C) 2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; either version 2 of the License, or
00006    (at your option) any later version.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
00016 
00017 #include "Backup.hpp"
00018 
00019 #include <ndb_version.h>
00020 
00021 #include <NdbTCP.h>
00022 #include <Bitmask.hpp>
00023 
00024 #include <signaldata/NodeFailRep.hpp>
00025 #include <signaldata/ReadNodesConf.hpp>
00026 
00027 #include <signaldata/ScanFrag.hpp>
00028 
00029 #include <signaldata/GetTabInfo.hpp>
00030 #include <signaldata/DictTabInfo.hpp>
00031 #include <signaldata/ListTables.hpp>
00032 
00033 #include <signaldata/FsOpenReq.hpp>
00034 #include <signaldata/FsAppendReq.hpp>
00035 #include <signaldata/FsCloseReq.hpp>
00036 #include <signaldata/FsConf.hpp>
00037 #include <signaldata/FsRef.hpp>
00038 #include <signaldata/FsRemoveReq.hpp>
00039 
00040 #include <signaldata/BackupImpl.hpp>
00041 #include <signaldata/BackupSignalData.hpp>
00042 #include <signaldata/BackupContinueB.hpp>
00043 #include <signaldata/EventReport.hpp>
00044 
00045 #include <signaldata/UtilSequence.hpp>
00046 
00047 #include <signaldata/CreateTrig.hpp>
00048 #include <signaldata/AlterTrig.hpp>
00049 #include <signaldata/DropTrig.hpp>
00050 #include <signaldata/FireTrigOrd.hpp>
00051 #include <signaldata/TrigAttrInfo.hpp>
00052 #include <AttributeHeader.hpp>
00053 
00054 #include <signaldata/WaitGCP.hpp>
00055 
00056 #include <NdbTick.h>
00057 
00058 static NDB_TICKS startTime;
00059 
00060 static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
00061 
00062 #ifdef VM_TRACE
00063 #define DEBUG_OUT(x) ndbout << x << endl
00064 #else
00065 #define DEBUG_OUT(x) 
00066 #endif
00067 
00068 //#define DEBUG_ABORT
00069 
00070 static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
00071 
00072 void
00073 Backup::execSTTOR(Signal* signal) 
00074 {
00075   jamEntry();                            
00076 
00077   const Uint32 startphase  = signal->theData[1];
00078   const Uint32 typeOfStart = signal->theData[7];
00079 
00080   if (startphase == 3) {
00081     jam();
00082     g_TypeOfStart = typeOfStart;
00083     signal->theData[0] = reference();
00084     sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
00085     return;
00086   }//if
00087 
00088   if(startphase == 7 && g_TypeOfStart == NodeState::ST_INITIAL_START &&
00089      c_masterNodeId == getOwnNodeId()){
00090     jam();
00091     createSequence(signal);
00092     return;
00093   }//if
00094   
00095   sendSTTORRY(signal);  
00096   return;
00097 }//Dbdict::execSTTOR()
00098 
00099 void
00100 Backup::execREAD_NODESCONF(Signal* signal)
00101 {
00102   jamEntry();
00103   ReadNodesConf * conf = (ReadNodesConf *)signal->getDataPtr();
00104  
00105   c_aliveNodes.clear();
00106 
00107   Uint32 count = 0;
00108   for (Uint32 i = 0; i<MAX_NDB_NODES; i++) {
00109     jam();
00110     if(NodeBitmask::get(conf->allNodes, i)){
00111       jam();
00112       count++;
00113 
00114       NodePtr node;
00115       ndbrequire(c_nodes.seize(node));
00116       
00117       node.p->nodeId = i;
00118       if(NodeBitmask::get(conf->inactiveNodes, i)) {
00119         jam();
00120         node.p->alive = 0;
00121       } else {
00122         jam();
00123         node.p->alive = 1;
00124         c_aliveNodes.set(i);
00125       }//if
00126     }//if
00127   }//for
00128   c_masterNodeId = conf->masterNodeId;
00129   ndbrequire(count == conf->noOfNodes);
00130   sendSTTORRY(signal);
00131 }
00132 
00133 void
00134 Backup::sendSTTORRY(Signal* signal)
00135 {
00136   signal->theData[0] = 0;
00137   signal->theData[3] = 1;
00138   signal->theData[4] = 3;
00139   signal->theData[5] = 7;
00140   signal->theData[6] = 255; // No more start phases from missra
00141   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
00142 }
00143 
00144 void
00145 Backup::createSequence(Signal* signal)
00146 {
00147   UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
00148   
00149   req->senderData  = RNIL;
00150   req->sequenceId  = BACKUP_SEQUENCE;
00151   req->requestType = UtilSequenceReq::Create;
00152   
00153   sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ, 
00154              signal, UtilSequenceReq::SignalLength, JBB);
00155 }
00156 
00157 void
00158 Backup::execCONTINUEB(Signal* signal)
00159 {
00160   jamEntry();
00161   const Uint32 Tdata0 = signal->theData[0];
00162   const Uint32 Tdata1 = signal->theData[1];
00163   const Uint32 Tdata2 = signal->theData[2];
00164   
00165   switch(Tdata0) {
00166   case BackupContinueB::START_FILE_THREAD:
00167   case BackupContinueB::BUFFER_UNDERFLOW:
00168   {
00169     jam();
00170     BackupFilePtr filePtr;
00171     c_backupFilePool.getPtr(filePtr, Tdata1);
00172     checkFile(signal, filePtr);
00173     return;
00174   }
00175   break;
00176   case BackupContinueB::BUFFER_FULL_SCAN:
00177   {
00178     jam();
00179     BackupFilePtr filePtr;
00180     c_backupFilePool.getPtr(filePtr, Tdata1);
00181     checkScan(signal, filePtr);
00182     return;
00183   }
00184   break;
00185   case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE:
00186   {
00187     jam();
00188     BackupFilePtr filePtr;
00189     c_backupFilePool.getPtr(filePtr, Tdata1);
00190     fragmentCompleted(signal, filePtr);
00191     return;
00192   }
00193   break;
00194   case BackupContinueB::BUFFER_FULL_META:
00195   {
00196     jam();
00197     BackupRecordPtr ptr;
00198     c_backupPool.getPtr(ptr, Tdata1);
00199     
00200     BackupFilePtr filePtr;
00201     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
00202     FsBuffer & buf = filePtr.p->operation.dataBuffer;
00203     
00204     if(buf.getFreeSize() + buf.getMinRead() < buf.getUsableSize()) {
00205       jam();
00206       TablePtr tabPtr;
00207       c_tablePool.getPtr(tabPtr, Tdata2);
00208       
00209       DEBUG_OUT("Backup - Buffer full - " << buf.getFreeSize()
00210                 << " + " << buf.getMinRead()
00211                 << " < " << buf.getUsableSize()
00212                 << " - tableId = " << tabPtr.p->tableId);
00213 
00214       signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
00215       signal->theData[1] = Tdata1;
00216       signal->theData[2] = Tdata2;
00217       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
00218       return;
00219     }//if
00220     
00221     TablePtr tabPtr;
00222     c_tablePool.getPtr(tabPtr, Tdata2);
00223     GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
00224     req->senderRef = reference();
00225     req->senderData = ptr.i;
00226     req->requestType = GetTabInfoReq::RequestById |
00227       GetTabInfoReq::LongSignalConf;
00228     req->tableId = tabPtr.p->tableId;
00229     sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal, 
00230                GetTabInfoReq::SignalLength, JBB);
00231     return;
00232   }
00233   default:
00234     ndbrequire(0);
00235   }//switch
00236 }
00237 
00238 void
00239 Backup::execDUMP_STATE_ORD(Signal* signal)
00240 {
00241   jamEntry();
00242   
00243   if(signal->theData[0] == 20){
00244     if(signal->length() > 1){
00245       c_defaults.m_dataBufferSize = (signal->theData[1] * 1024 * 1024);
00246     }
00247     if(signal->length() > 2){
00248       c_defaults.m_logBufferSize = (signal->theData[2] * 1024 * 1024);
00249     }
00250     if(signal->length() > 3){
00251       c_defaults.m_minWriteSize = signal->theData[3] * 1024;
00252     }
00253     if(signal->length() > 4){
00254       c_defaults.m_maxWriteSize = signal->theData[4] * 1024;
00255     }
00256     
00257     infoEvent("Backup: data: %d log: %d min: %d max: %d",
00258               c_defaults.m_dataBufferSize,
00259               c_defaults.m_logBufferSize,
00260               c_defaults.m_minWriteSize,
00261               c_defaults.m_maxWriteSize);
00262     return;
00263   }
00264   if(signal->theData[0] == 21){
00265     BackupReq * req = (BackupReq*)signal->getDataPtrSend();
00266     req->senderData = 23;
00267     req->backupDataLen = 0;
00268     sendSignal(BACKUP_REF, GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
00269     startTime = NdbTick_CurrentMillisecond();
00270     return;
00271   }
00272 
00273   if(signal->theData[0] == 22){
00274     const Uint32 seq = signal->theData[1];
00275     FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
00276     req->userReference = reference();
00277     req->userPointer = 23;
00278     req->directory = 1;
00279     req->ownDirectory = 1;
00280     FsOpenReq::setVersion(req->fileNumber, 2);
00281     FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
00282     FsOpenReq::v2_setSequence(req->fileNumber, seq);
00283     FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
00284     sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, 
00285                FsRemoveReq::SignalLength, JBA);
00286     return;
00287   }
00288 
00289   if(signal->theData[0] == 23){
00293     BackupRecordPtr ptr;
00294     for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){
00295       infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x",
00296                 ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
00297       infoEvent(" State: %d", ptr.p->slaveState.getState());
00298       BackupFilePtr filePtr;
00299       for(ptr.p->files.first(filePtr); filePtr.i != RNIL; 
00300           ptr.p->files.next(filePtr)){
00301         jam();
00302         infoEvent(" file %d: type: %d open: %d running: %d done: %d scan: %d",
00303                   filePtr.i, filePtr.p->fileType, filePtr.p->fileOpened,
00304                   filePtr.p->fileRunning, 
00305                   filePtr.p->fileClosing, filePtr.p->scanRunning);
00306       }
00307     }
00308   }
00309   if(signal->theData[0] == 24){
00313     infoEvent("Backup - dump pool sizes");
00314     infoEvent("BackupPool: %d BackupFilePool: %d TablePool: %d",
00315               c_backupPool.getSize(), c_backupFilePool.getSize(), 
00316               c_tablePool.getSize());
00317     infoEvent("AttrPool: %d TriggerPool: %d FragmentPool: %d",
00318               c_backupPool.getSize(), c_backupFilePool.getSize(), 
00319               c_tablePool.getSize());
00320     infoEvent("PagePool: %d",
00321               c_pagePool.getSize());
00322 
00323 
00324     if(signal->getLength() == 2 && signal->theData[1] == 2424)
00325     {
00326       ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree());
00327       ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree());
00328       ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree());
00329       ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree());
00330       ndbrequire(c_pagePool.getSize() == c_pagePool.getNoOfFree());
00331       ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree());
00332       ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree());
00333     }
00334   }
00335 }
00336 
00337 bool
00338 Backup::findTable(const BackupRecordPtr & ptr, 
00339                   TablePtr & tabPtr, Uint32 tableId) const
00340 {
00341   for(ptr.p->tables.first(tabPtr); 
00342       tabPtr.i != RNIL; 
00343       ptr.p->tables.next(tabPtr)) {
00344     jam();
00345     if(tabPtr.p->tableId == tableId){
00346       jam();
00347       return true;
00348     }//if
00349   }//for
00350   tabPtr.i = RNIL;
00351   tabPtr.p = 0;
00352   return false;
00353 }
00354 
00355 static Uint32 xps(Uint32 x, Uint64 ms)
00356 {
00357   float fx = x;
00358   float fs = ms;
00359   
00360   if(ms == 0 || x == 0) {
00361     jam();
00362     return 0;
00363   }//if
00364   jam();
00365   return ((Uint32)(1000.0f * (fx + fs/2.1f))) / ((Uint32)fs);
00366 }
00367 
00368 struct Number {
00369   Number(Uint32 r) { val = r;}
00370   Number & operator=(Uint32 r) { val = r; return * this; }
00371   Uint32 val;
00372 };
00373 
00374 NdbOut &
00375 operator<< (NdbOut & out, const Number & val){
00376   char p = 0;
00377   Uint32 loop = 1;
00378   while(val.val > loop){
00379     loop *= 1000;
00380     p += 3;
00381   }
00382   if(loop != 1){
00383     p -= 3;
00384     loop /= 1000;
00385   }
00386 
00387   switch(p){
00388   case 0:
00389     break;
00390   case 3:
00391     p = 'k';
00392     break;
00393   case 6:
00394     p = 'M';
00395     break;
00396   case 9:
00397     p = 'G';
00398     break;
00399   default:
00400     p = 0;
00401   }
00402   char str[2];
00403   str[0] = p;
00404   str[1] = 0;
00405   Uint32 tmp = (val.val + (loop >> 1)) / loop;
00406 #if 1
00407   if(p > 0)
00408     out << tmp << str;
00409   else
00410     out << tmp;
00411 #else
00412   out << val.val;
00413 #endif
00414 
00415   return out;
00416 }
00417 
00418 void
00419 Backup::execBACKUP_CONF(Signal* signal)
00420 {
00421   jamEntry();
00422   BackupConf * conf = (BackupConf*)signal->getDataPtr();
00423   
00424   ndbout_c("Backup %d has started", conf->backupId);
00425 }
00426 
00427 void
00428 Backup::execBACKUP_REF(Signal* signal)
00429 {
00430   jamEntry();
00431   BackupRef * ref = (BackupRef*)signal->getDataPtr();
00432 
00433   ndbout_c("Backup (%d) has NOT started %d", ref->senderData, ref->errorCode);
00434 }
00435 
00436 void
00437 Backup::execBACKUP_COMPLETE_REP(Signal* signal)
00438 {
00439   jamEntry();
00440   BackupCompleteRep* rep = (BackupCompleteRep*)signal->getDataPtr();
00441  
00442   startTime = NdbTick_CurrentMillisecond() - startTime;
00443   
00444   ndbout_c("Backup %d has completed", rep->backupId);
00445   const Uint32 bytes = rep->noOfBytes;
00446   const Uint32 records = rep->noOfRecords;
00447 
00448   Number rps = xps(records, startTime);
00449   Number bps = xps(bytes, startTime);
00450 
00451   ndbout << " Data [ "
00452          << Number(records) << " rows " 
00453          << Number(bytes) << " bytes " << startTime << " ms ] " 
00454          << " => "
00455          << rps << " row/s & " << bps << "b/s" << endl;
00456 
00457   bps = xps(rep->noOfLogBytes, startTime);
00458   rps = xps(rep->noOfLogRecords, startTime);
00459 
00460   ndbout << " Log [ "
00461          << Number(rep->noOfLogRecords) << " log records " 
00462          << Number(rep->noOfLogBytes) << " bytes " << startTime << " ms ] " 
00463          << " => "
00464          << rps << " records/s & " << bps << "b/s" << endl;
00465 
00466 }
00467 
00468 void
00469 Backup::execBACKUP_ABORT_REP(Signal* signal)
00470 {
00471   jamEntry();
00472   BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtr();
00473   
00474   ndbout_c("Backup %d has been aborted %d", rep->backupId, rep->reason);
00475 }
00476 
00477 const TriggerEvent::Value triggerEventValues[] = {
00478   TriggerEvent::TE_INSERT,
00479   TriggerEvent::TE_UPDATE,
00480   TriggerEvent::TE_DELETE
00481 };
00482 
00483 const char* triggerNameFormat[] = {
00484   "NDB$BACKUP_%d_%d_INSERT",
00485   "NDB$BACKUP_%d_%d_UPDATE",
00486   "NDB$BACKUP_%d_%d_DELETE"
00487 };
00488 
00489 const Backup::State 
00490 Backup::validSlaveTransitions[] = {
00491   INITIAL,  DEFINING,
00492   DEFINING, DEFINED,
00493   DEFINED,  STARTED,
00494   STARTED,  STARTED, // Several START_BACKUP_REQ is sent
00495   STARTED,  SCANNING,
00496   SCANNING, STARTED,
00497   STARTED,  STOPPING,
00498   STOPPING, CLEANING,
00499   CLEANING, INITIAL,
00500   
00501   INITIAL,  ABORTING, // Node fail
00502   DEFINING, ABORTING,
00503   DEFINED,  ABORTING,
00504   STARTED,  ABORTING,
00505   SCANNING, ABORTING,
00506   STOPPING, ABORTING,
00507   CLEANING, ABORTING, // Node fail w/ master takeover
00508   ABORTING, ABORTING, // Slave who initiates ABORT should have this transition
00509   
00510   ABORTING, INITIAL,
00511   INITIAL,  INITIAL
00512 };
00513 
00514 const Uint32
00515 Backup::validSlaveTransitionsCount = 
00516 sizeof(Backup::validSlaveTransitions) / sizeof(Backup::State);
00517 
00518 void
00519 Backup::CompoundState::setState(State newState){
00520   bool found = false;
00521   const State currState = state;
00522   for(unsigned i = 0; i<noOfValidTransitions; i+= 2) {
00523     jam();
00524     if(validTransitions[i]   == currState &&
00525        validTransitions[i+1] == newState){
00526       jam();
00527       found = true;
00528       break;
00529     }
00530   }
00531 
00532   //ndbrequire(found);
00533   
00534   if (newState == INITIAL)
00535     abortState = INITIAL;
00536   if(newState == ABORTING && currState != ABORTING) {
00537     jam();
00538     abortState = currState;
00539   }
00540   state = newState;
00541 #ifdef DEBUG_ABORT
00542   if (newState != currState) {
00543     ndbout_c("%u: Old state = %u, new state = %u, abort state = %u",
00544              id, currState, newState, abortState);
00545   }
00546 #endif
00547 }
00548 
00549 void
00550 Backup::CompoundState::forceState(State newState)
00551 {
00552   const State currState = state;
00553   if (newState == INITIAL)
00554     abortState = INITIAL;
00555   if(newState == ABORTING && currState != ABORTING) {
00556     jam();
00557     abortState = currState;
00558   }
00559   state = newState;
00560 #ifdef DEBUG_ABORT
00561   if (newState != currState) {
00562     ndbout_c("%u: FORCE: Old state = %u, new state = %u, abort state = %u",
00563              id, currState, newState, abortState);
00564   }
00565 #endif
00566 }
00567 
00568 Backup::Table::Table(ArrayPool<Attribute> & ah, 
00569                      ArrayPool<Fragment> & fh) 
00570   : attributes(ah), fragments(fh)
00571 {
00572   triggerIds[0] = ILLEGAL_TRIGGER_ID;
00573   triggerIds[1] = ILLEGAL_TRIGGER_ID;
00574   triggerIds[2] = ILLEGAL_TRIGGER_ID;
00575   triggerAllocated[0] = false;
00576   triggerAllocated[1] = false;
00577   triggerAllocated[2] = false;
00578 }
00579 
00580 /*****************************************************************************
00581  * 
00582  * Node state handling
00583  *
00584  *****************************************************************************/
00585 void
00586 Backup::execNODE_FAILREP(Signal* signal)
00587 {
00588   jamEntry();
00589 
00590   NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
00591   
00592   bool doStuff = false;
00593   /*
00594   Start by saving important signal data which will be destroyed before the
00595   process is completed.
00596   */
00597   NodeId new_master_node_id = rep->masterNodeId;
00598   Uint32 theFailedNodes[NodeBitmask::Size];
00599   for (Uint32 i = 0; i < NodeBitmask::Size; i++)
00600     theFailedNodes[i] = rep->theNodes[i];
00601   
00602   c_masterNodeId = new_master_node_id;
00603 
00604   NodePtr nodePtr;
00605   for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
00606     jam();
00607     if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)){
00608       if(nodePtr.p->alive){
00609         jam();
00610         ndbrequire(c_aliveNodes.get(nodePtr.p->nodeId));
00611         doStuff = true;
00612       } else {
00613         jam();
00614         ndbrequire(!c_aliveNodes.get(nodePtr.p->nodeId));
00615       }//if
00616       nodePtr.p->alive = 0;
00617       c_aliveNodes.clear(nodePtr.p->nodeId);
00618     }//if
00619   }//for
00620 
00621   if(!doStuff){
00622     jam();
00623     return;
00624   }//if
00625   
00626 #ifdef DEBUG_ABORT
00627   ndbout_c("****************** Node fail rep ******************");
00628 #endif
00629 
00630   NodeId newCoordinator = c_masterNodeId;
00631   BackupRecordPtr ptr;
00632   for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
00633     jam();
00634     checkNodeFail(signal, ptr, newCoordinator, theFailedNodes);
00635   }
00636 }
00637 
00638 bool
00639 Backup::verifyNodesAlive(BackupRecordPtr ptr,
00640                          const NdbNodeBitmask& aNodeBitMask)
00641 {
00642   Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
00643   for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
00644     jam();
00645     if(aNodeBitMask.get(i)) {
00646       if(!c_aliveNodes.get(i)){
00647         jam();
00648         ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
00649         return false;
00650       }//if
00651       if(getNodeInfo(i).m_version != version)
00652       {
00653         jam();
00654         ptr.p->setErrorCode(AbortBackupOrd::IncompatibleVersions);
00655         return false;
00656       }
00657     }//if
00658   }//for
00659   return true;
00660 }
00661 
00662 void
00663 Backup::checkNodeFail(Signal* signal,
00664                       BackupRecordPtr ptr,
00665                       NodeId newCoord,
00666                       Uint32 theFailedNodes[NodeBitmask::Size])
00667 {
00668   NdbNodeBitmask mask;
00669   mask.assign(2, theFailedNodes);
00670 
00671   /* Update ptr.p->nodes to be up to date with current alive nodes
00672    */
00673   NodePtr nodePtr;
00674   bool found = false;
00675   for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
00676     jam();
00677     if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)) {
00678       jam();
00679       if (ptr.p->nodes.get(nodePtr.p->nodeId)) {
00680         jam();
00681         ptr.p->nodes.clear(nodePtr.p->nodeId); 
00682         found = true;
00683       }
00684     }//if
00685   }//for
00686 
00687   if(!found) {
00688     jam();
00689     return; // failed node is not part of backup process, safe to continue
00690   }
00691 
00692   if(mask.get(refToNode(ptr.p->masterRef)))
00693   {
00697     ptr.p->masterRef = reference();
00698     ptr.p->nodes.clear();
00699     ptr.p->nodes.set(getOwnNodeId());
00700     ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
00701     switch(ptr.p->m_gsn){
00702     case GSN_DEFINE_BACKUP_REQ:
00703     case GSN_START_BACKUP_REQ:
00704     case GSN_BACKUP_FRAGMENT_REQ:
00705     case GSN_STOP_BACKUP_REQ:
00706       // I'm currently processing...reply to self and abort...
00707       ptr.p->masterData.gsn = ptr.p->m_gsn;
00708       ptr.p->masterData.sendCounter = ptr.p->nodes;
00709       return;
00710     case GSN_DEFINE_BACKUP_REF:
00711     case GSN_DEFINE_BACKUP_CONF:
00712     case GSN_START_BACKUP_REF:
00713     case GSN_START_BACKUP_CONF:
00714     case GSN_BACKUP_FRAGMENT_REF:
00715     case GSN_BACKUP_FRAGMENT_CONF:
00716     case GSN_STOP_BACKUP_REF:
00717     case GSN_STOP_BACKUP_CONF:
00718       ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
00719       masterAbort(signal, ptr);
00720       return;
00721     case GSN_ABORT_BACKUP_ORD:
00722       // Already aborting
00723       return;
00724     }
00725   }
00726   else if (newCoord == getOwnNodeId())
00727   {
00731     jam();
00732     CRASH_INSERTION((10001));
00733 #ifdef DEBUG_ABORT
00734     ndbout_c("**** Master: Node failed: Master id = %u", 
00735              refToNode(ptr.p->masterRef));
00736 #endif
00737 
00738     Uint32 gsn, len, pos;
00739     ptr.p->nodes.bitANDC(mask);
00740     switch(ptr.p->masterData.gsn){
00741     case GSN_DEFINE_BACKUP_REQ:
00742     {
00743       DefineBackupRef * ref = (DefineBackupRef*)signal->getDataPtr();
00744       ref->backupPtr = ptr.i;
00745       ref->backupId = ptr.p->backupId;
00746       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
00747       gsn= GSN_DEFINE_BACKUP_REF;
00748       len= DefineBackupRef::SignalLength;
00749       pos= &ref->nodeId - signal->getDataPtr();
00750       break;
00751     }
00752     case GSN_START_BACKUP_REQ:
00753     {
00754       StartBackupRef * ref = (StartBackupRef*)signal->getDataPtr();
00755       ref->backupPtr = ptr.i;
00756       ref->backupId = ptr.p->backupId;
00757       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
00758       ref->signalNo = ptr.p->masterData.startBackup.signalNo;
00759       gsn= GSN_START_BACKUP_REF;
00760       len= StartBackupRef::SignalLength;
00761       pos= &ref->nodeId - signal->getDataPtr();
00762       break;
00763     }
00764     case GSN_BACKUP_FRAGMENT_REQ:
00765     {
00766       BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
00767       ref->backupPtr = ptr.i;
00768       ref->backupId = ptr.p->backupId;
00769       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
00770       gsn= GSN_BACKUP_FRAGMENT_REF;
00771       len= BackupFragmentRef::SignalLength;
00772       pos= &ref->nodeId - signal->getDataPtr();
00773       break;
00774     }
00775     case GSN_STOP_BACKUP_REQ:
00776     {
00777       StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
00778       ref->backupPtr = ptr.i;
00779       ref->backupId = ptr.p->backupId;
00780       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
00781       gsn= GSN_STOP_BACKUP_REF;
00782       len= StopBackupRef::SignalLength;
00783       pos= &ref->nodeId - signal->getDataPtr();
00784       break;
00785     }
00786     case GSN_CREATE_TRIG_REQ:
00787     case GSN_ALTER_TRIG_REQ:
00788     case GSN_WAIT_GCP_REQ:
00789     case GSN_UTIL_SEQUENCE_REQ:
00790     case GSN_UTIL_LOCK_REQ:
00791     case GSN_DROP_TRIG_REQ:
00792       return;
00793     }
00794     
00795     for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; )
00796     {
00797       signal->theData[pos] = i;
00798       sendSignal(reference(), gsn, signal, len, JBB);
00799 #ifdef DEBUG_ABORT
00800       ndbout_c("sending %d to self from %d", gsn, i);
00801 #endif
00802     }
00803     return;
00804   }//if
00805   
00809   CRASH_INSERTION((10021));
00810 } 
00811 
00812 void
00813 Backup::execINCL_NODEREQ(Signal* signal)
00814 {
00815   jamEntry();
00816   
00817   const Uint32 senderRef = signal->theData[0];
00818   const Uint32 inclNode  = signal->theData[1];
00819 
00820   NodePtr node;
00821   for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
00822     jam();
00823     const Uint32 nodeId = node.p->nodeId;
00824     if(inclNode == nodeId){
00825       jam();
00826       
00827       ndbrequire(node.p->alive == 0);
00828       ndbrequire(!c_aliveNodes.get(nodeId));
00829       
00830       node.p->alive = 1;
00831       c_aliveNodes.set(nodeId);
00832       
00833       break;
00834     }//if
00835   }//for
00836   signal->theData[0] = reference();
00837   sendSignal(senderRef, GSN_INCL_NODECONF, signal, 1, JBB);
00838 }
00839 
00840 /*****************************************************************************
00841  * 
00842  * Master functionallity - Define backup
00843  *
00844  *****************************************************************************/
00845 
00846 void
00847 Backup::execBACKUP_REQ(Signal* signal)
00848 {
00849   jamEntry();
00850   BackupReq * req = (BackupReq*)signal->getDataPtr();
00851   
00852   const Uint32 senderData = req->senderData;
00853   const BlockReference senderRef = signal->senderBlockRef();
00854   const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
00855   
00856   if(getOwnNodeId() != getMasterNodeId()) {
00857     jam();
00858     sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
00859     return;
00860   }//if
00861 
00862   if (m_diskless)
00863   {
00864     sendBackupRef(senderRef, signal, senderData, 
00865                   BackupRef::CannotBackupDiskless);
00866     return;
00867   }
00868   
00869   if(dataLen32 != 0) {
00870     jam();
00871     sendBackupRef(senderRef, signal, senderData, 
00872                   BackupRef::BackupDefinitionNotImplemented);
00873     return;
00874   }//if
00875   
00876 #ifdef DEBUG_ABORT
00877   dumpUsedResources();
00878 #endif
00879 
00882   BackupRecordPtr ptr;
00883   c_backups.seize(ptr);
00884   if(ptr.i == RNIL) {
00885     jam();
00886     sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord);
00887     return;
00888   }//if
00889 
00890   ndbrequire(ptr.p->pages.empty());
00891   ndbrequire(ptr.p->tables.isEmpty());
00892   
00893   ptr.p->m_gsn = 0;
00894   ptr.p->errorCode = 0;
00895   ptr.p->clientRef = senderRef;
00896   ptr.p->clientData = senderData;
00897   ptr.p->masterRef = reference();
00898   ptr.p->nodes = c_aliveNodes;
00899   ptr.p->backupId = 0;
00900   ptr.p->backupKey[0] = 0;
00901   ptr.p->backupKey[1] = 0;
00902   ptr.p->backupDataLen = 0;
00903   ptr.p->masterData.errorCode = 0;
00904   ptr.p->masterData.dropTrig.tableId = RNIL;
00905   ptr.p->masterData.alterTrig.tableId = RNIL;
00906   
00907   UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
00908     
00909   ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ;
00910   utilReq->senderData  = ptr.i;
00911   utilReq->sequenceId  = BACKUP_SEQUENCE;
00912   utilReq->requestType = UtilSequenceReq::NextVal;
00913   sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ, 
00914              signal, UtilSequenceReq::SignalLength, JBB);
00915 }
00916 
00917 void
00918 Backup::execUTIL_SEQUENCE_REF(Signal* signal)
00919 {
00920   BackupRecordPtr ptr;
00921   jamEntry();
00922   UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr();
00923   ptr.i = utilRef->senderData;
00924   ndbrequire(ptr.i == RNIL);
00925   c_backupPool.getPtr(ptr);
00926   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
00927   sendBackupRef(signal, ptr, BackupRef::SequenceFailure);
00928 }//execUTIL_SEQUENCE_REF()
00929 
00930 
00931 void
00932 Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
00933 {
00934   jam();
00935   sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode);
00936   cleanup(signal, ptr);
00937 }
00938 
00939 void
00940 Backup::sendBackupRef(BlockReference senderRef, Signal *signal,
00941                       Uint32 senderData, Uint32 errorCode)
00942 {
00943   jam();
00944   BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
00945   ref->senderData = senderData;
00946   ref->errorCode = errorCode;
00947   ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
00948   sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
00949 
00950   if(errorCode != BackupRef::IAmNotMaster){
00951     signal->theData[0] = NDB_LE_BackupFailedToStart;
00952     signal->theData[1] = senderRef;
00953     signal->theData[2] = errorCode;
00954     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
00955   }
00956 }
00957 
00958 void
00959 Backup::execUTIL_SEQUENCE_CONF(Signal* signal)
00960 {
00961   jamEntry();
00962 
00963   UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
00964   
00965   if(conf->requestType == UtilSequenceReq::Create) 
00966   {
00967     jam();
00968     sendSTTORRY(signal); // At startup in NDB
00969     return;
00970   }
00971 
00972   BackupRecordPtr ptr;
00973   ptr.i = conf->senderData;
00974   c_backupPool.getPtr(ptr);
00975 
00976   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
00977 
00978   if (ptr.p->checkError())
00979   {
00980     jam();
00981     sendBackupRef(signal, ptr, ptr.p->errorCode);
00982     return;
00983   }//if
00984 
00985   if (ERROR_INSERTED(10023)) 
00986   {
00987     sendBackupRef(signal, ptr, 323);
00988     return;
00989   }//if
00990 
00991 
00992   {
00993     Uint64 backupId;
00994     memcpy(&backupId,conf->sequenceValue,8);
00995     ptr.p->backupId= (Uint32)backupId;
00996   }
00997   ptr.p->backupKey[0] = (getOwnNodeId() << 16) | (ptr.p->backupId & 0xFFFF);
00998   ptr.p->backupKey[1] = NdbTick_CurrentMillisecond();
00999 
01000   ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
01001   Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
01002   Callback c = { safe_cast(&Backup::defineBackupMutex_locked), ptr.i };
01003   ndbrequire(mutex.lock(c));
01004 
01005   return;
01006 }
01007 
01008 void
01009 Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
01010   jamEntry();
01011   ndbrequire(retVal == 0);
01012   
01013   BackupRecordPtr ptr;
01014   ptr.i = ptrI;
01015   c_backupPool.getPtr(ptr);
01016   
01017   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
01018 
01019   ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
01020   Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
01021   Callback c = { safe_cast(&Backup::dictCommitTableMutex_locked), ptr.i };
01022   ndbrequire(mutex.lock(c));
01023 }
01024 
01025 void
01026 Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal)
01027 {
01028   jamEntry();
01029   ndbrequire(retVal == 0);
01030   
01034   BackupRecordPtr ptr;
01035   ptr.i = ptrI;
01036   c_backupPool.getPtr(ptr);
01037 
01038   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
01039 
01040   if (ERROR_INSERTED(10031)) {
01041     ptr.p->setErrorCode(331);
01042   }//if
01043 
01044   if (ptr.p->checkError())
01045   {
01046     jam();
01047     
01051     jam();
01052     Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
01053     jam();
01054     mutex1.unlock(); // ignore response
01055     
01056     jam();
01057     Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
01058     jam();
01059     mutex2.unlock(); // ignore response
01060     
01061     sendBackupRef(signal, ptr, ptr.p->errorCode);
01062     return;
01063   }//if
01064   
01065   sendDefineBackupReq(signal, ptr);
01066 }
01067 
01068 /*****************************************************************************
01069  * 
01070  * Master functionallity - Define backup cont'd (from now on all slaves are in)
01071  *
01072  *****************************************************************************/
01073 
01074 bool
01075 Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId)
01076 { 
01077   ndbrequire(ptr.p->masterRef == reference());
01078   ndbrequire(ptr.p->masterData.gsn == gsn);
01079   ndbrequire(!ptr.p->masterData.sendCounter.done());
01080   ndbrequire(ptr.p->masterData.sendCounter.isWaitingFor(nodeId));
01081   
01082   ptr.p->masterData.sendCounter.clearWaitingFor(nodeId);
01083   return ptr.p->masterData.sendCounter.done();
01084 }
01085 
01086 void
01087 Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
01088 {
01092   DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
01093   req->backupId = ptr.p->backupId;
01094   req->clientRef = ptr.p->clientRef;
01095   req->clientData = ptr.p->clientData;
01096   req->senderRef = reference();
01097   req->backupPtr = ptr.i;
01098   req->backupKey[0] = ptr.p->backupKey[0];
01099   req->backupKey[1] = ptr.p->backupKey[1];
01100   req->nodes = ptr.p->nodes;
01101   req->backupDataLen = ptr.p->backupDataLen;
01102   
01103   ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
01104   ptr.p->masterData.sendCounter = ptr.p->nodes;
01105   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
01106   sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal, 
01107              DefineBackupReq::SignalLength, JBB);
01108   
01112   const Uint32 len = ptr.p->backupDataLen;
01113   if(len == 0){
01117     jam();
01118     return;
01119   }//if
01120   
01124   ndbrequire(0);
01125 }
01126 
01127 void
01128 Backup::execDEFINE_BACKUP_REF(Signal* signal)
01129 {
01130   jamEntry();
01131 
01132   DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtr();
01133   
01134   const Uint32 ptrI = ref->backupPtr;
01135   //const Uint32 backupId = ref->backupId;
01136   const Uint32 nodeId = ref->nodeId;
01137   
01138   BackupRecordPtr ptr;
01139   c_backupPool.getPtr(ptr, ptrI);
01140   
01141   ptr.p->setErrorCode(ref->errorCode);
01142   defineBackupReply(signal, ptr, nodeId);
01143 }
01144 
01145 void
01146 Backup::execDEFINE_BACKUP_CONF(Signal* signal)
01147 {
01148   jamEntry();
01149 
01150   DefineBackupConf* conf = (DefineBackupConf*)signal->getDataPtr();
01151   const Uint32 ptrI = conf->backupPtr;
01152   //const Uint32 backupId = conf->backupId;
01153   const Uint32 nodeId = refToNode(signal->senderBlockRef());
01154 
01155   BackupRecordPtr ptr;
01156   c_backupPool.getPtr(ptr, ptrI);
01157 
01158   if (ERROR_INSERTED(10024))
01159   {
01160     ptr.p->setErrorCode(324);
01161   }
01162 
01163   defineBackupReply(signal, ptr, nodeId);
01164 }
01165 
01166 void
01167 Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
01168 {
01169   if (!haveAllSignals(ptr, GSN_DEFINE_BACKUP_REQ, nodeId)) {
01170     jam();
01171     return;
01172   }
01173 
01177   jam();
01178   Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
01179   jam();
01180   mutex1.unlock(); // ignore response
01181 
01182   jam();
01183   Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
01184   jam();
01185   mutex2.unlock(); // ignore response
01186 
01187   if(ptr.p->checkError())
01188   {
01189     jam();
01190     masterAbort(signal, ptr);
01191     return;
01192   }
01193   
01197   BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
01198   conf->backupId = ptr.p->backupId;
01199   conf->senderData = ptr.p->clientData;
01200   conf->nodes = ptr.p->nodes;
01201   sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal, 
01202              BackupConf::SignalLength, JBB);
01203   
01204   signal->theData[0] = NDB_LE_BackupStarted;
01205   signal->theData[1] = ptr.p->clientRef;
01206   signal->theData[2] = ptr.p->backupId;
01207   ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
01208   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
01209   
01213   TablePtr tabPtr;
01214   ndbrequire(ptr.p->tables.first(tabPtr));
01215   sendCreateTrig(signal, ptr, tabPtr);
01216 }
01217 
01218 /*****************************************************************************
01219  * 
01220  * Master functionallity - Prepare triggers
01221  *
01222  *****************************************************************************/
01223 void
01224 Backup::createAttributeMask(TablePtr tabPtr, 
01225                             Bitmask<MAXNROFATTRIBUTESINWORDS> & mask)
01226 {
01227   mask.clear();
01228   Table & table = * tabPtr.p;
01229   for(Uint32 i = 0; i<table.noOfAttributes; i++) {
01230     jam();
01231     AttributePtr attr;
01232     table.attributes.getPtr(attr, i);
01233     mask.set(i);
01234   }
01235 }
01236 
01237 void
01238 Backup::sendCreateTrig(Signal* signal, 
01239                            BackupRecordPtr ptr, TablePtr tabPtr)
01240 {
01241   CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend();
01242   
01243   ptr.p->masterData.gsn = GSN_CREATE_TRIG_REQ;
01244   ptr.p->masterData.sendCounter = 3;
01245   ptr.p->masterData.createTrig.tableId = tabPtr.p->tableId;
01246 
01247   req->setUserRef(reference());
01248   req->setConnectionPtr(ptr.i);
01249   req->setRequestType(CreateTrigReq::RT_USER);
01250   
01251   Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask;
01252   createAttributeMask(tabPtr, attrMask);
01253   req->setAttributeMask(attrMask);
01254   req->setTableId(tabPtr.p->tableId);
01255   req->setIndexId(RNIL);        // not used
01256   req->setTriggerId(RNIL);      // to be created
01257   req->setTriggerType(TriggerType::SUBSCRIPTION);
01258   req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
01259   req->setMonitorReplicas(true);
01260   req->setMonitorAllAttributes(false);
01261   req->setOnline(false);        // leave trigger offline
01262 
01263   char triggerName[MAX_TAB_NAME_SIZE];
01264   Uint32 nameBuffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];  // SP string
01265   LinearWriter w(nameBuffer, sizeof(nameBuffer) >> 2);
01266   LinearSectionPtr lsPtr[3];
01267   
01268   for (int i=0; i < 3; i++) {
01269     req->setTriggerEvent(triggerEventValues[i]);
01270     BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
01271              ptr.p->backupId, tabPtr.p->tableId);
01272     w.reset();
01273     w.add(CreateTrigReq::TriggerNameKey, triggerName);
01274     lsPtr[0].p = nameBuffer;
01275     lsPtr[0].sz = w.getWordsUsed();
01276     sendSignal(DBDICT_REF, GSN_CREATE_TRIG_REQ, 
01277                signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
01278   }
01279 }
01280 
01281 void
01282 Backup::execCREATE_TRIG_CONF(Signal* signal)
01283 {
01284   jamEntry();
01285   CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtr();
01286   
01287   const Uint32 ptrI = conf->getConnectionPtr();
01288   const Uint32 tableId = conf->getTableId();
01289   const TriggerEvent::Value type = conf->getTriggerEvent();
01290   const Uint32 triggerId = conf->getTriggerId();
01291 
01292   BackupRecordPtr ptr;
01293   c_backupPool.getPtr(ptr, ptrI);
01294 
01298   ndbrequire(ptr.p->masterRef == reference());
01299   ndbrequire(ptr.p->masterData.gsn == GSN_CREATE_TRIG_REQ);
01300   ndbrequire(ptr.p->masterData.sendCounter.done() == false);
01301   ndbrequire(ptr.p->masterData.createTrig.tableId == tableId);
01302   
01303   TablePtr tabPtr;
01304   ndbrequire(findTable(ptr, tabPtr, tableId));
01305   ndbrequire(type < 3); // if some decides to change the enums
01306 
01307   ndbrequire(tabPtr.p->triggerIds[type] == ILLEGAL_TRIGGER_ID);
01308   tabPtr.p->triggerIds[type] = triggerId;
01309   
01310   createTrigReply(signal, ptr);
01311 }
01312 
01313 void
01314 Backup::execCREATE_TRIG_REF(Signal* signal)
01315 {
01316   CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr();
01317 
01318   const Uint32 ptrI = ref->getConnectionPtr();
01319   const Uint32 tableId = ref->getTableId();
01320 
01321   BackupRecordPtr ptr;
01322   c_backupPool.getPtr(ptr, ptrI);
01323 
01327   ndbrequire(ptr.p->masterRef == reference());
01328   ndbrequire(ptr.p->masterData.gsn == GSN_CREATE_TRIG_REQ);
01329   ndbrequire(ptr.p->masterData.sendCounter.done() == false);
01330   ndbrequire(ptr.p->masterData.createTrig.tableId == tableId);
01331 
01332   ptr.p->setErrorCode(ref->getErrorCode());
01333   
01334   createTrigReply(signal, ptr);
01335 }
01336 
01337 void
01338 Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
01339 {
01340   CRASH_INSERTION(10003);
01341 
01345   ptr.p->masterData.sendCounter--;
01346   if(ptr.p->masterData.sendCounter.done() == false){
01347     jam();
01348     return;
01349   }//if
01350 
01351   if (ERROR_INSERTED(10025)) 
01352   {
01353     ptr.p->errorCode = 325;
01354   }
01355 
01356   if(ptr.p->checkError()) {
01357     jam();
01358     masterAbort(signal, ptr);
01359     return;
01360   }//if
01361 
01362   TablePtr tabPtr;
01363   ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.createTrig.tableId));
01364   
01368   ptr.p->tables.next(tabPtr);
01369   if(tabPtr.i != RNIL){
01370     jam();
01371     sendCreateTrig(signal, ptr, tabPtr);
01372     return;
01373   }//if
01374 
01378   ptr.p->tables.first(tabPtr);
01379   ptr.p->masterData.startBackup.signalNo = 0;
01380   ptr.p->masterData.startBackup.noOfSignals = 
01381     (ptr.p->tables.noOfElements() + StartBackupReq::MaxTableTriggers - 1) / 
01382     StartBackupReq::MaxTableTriggers;
01383   sendStartBackup(signal, ptr, tabPtr);
01384 }
01385 
01386 /*****************************************************************************
01387  * 
01388  * Master functionallity - Start backup
01389  *
01390  *****************************************************************************/
01391 void
01392 Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
01393 {
01394 
01395   ptr.p->masterData.startBackup.tablePtr = tabPtr.i;
01396   
01397   StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend();
01398   req->backupId = ptr.p->backupId;
01399   req->backupPtr = ptr.i;
01400   req->signalNo = ptr.p->masterData.startBackup.signalNo;
01401   req->noOfSignals = ptr.p->masterData.startBackup.noOfSignals;
01402   Uint32 i;
01403   for(i = 0; i<StartBackupReq::MaxTableTriggers; i++) {
01404     jam();
01405     req->tableTriggers[i].tableId = tabPtr.p->tableId;
01406     req->tableTriggers[i].triggerIds[0] = tabPtr.p->triggerIds[0];
01407     req->tableTriggers[i].triggerIds[1] = tabPtr.p->triggerIds[1];
01408     req->tableTriggers[i].triggerIds[2] = tabPtr.p->triggerIds[2];
01409     if(!ptr.p->tables.next(tabPtr)){
01410       jam();
01411       i++;
01412       break;
01413     }//if
01414   }//for
01415   req->noOfTableTriggers = i;
01416 
01417   ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
01418   ptr.p->masterData.sendCounter = ptr.p->nodes;
01419   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
01420   sendSignal(rg, GSN_START_BACKUP_REQ, signal, 
01421              StartBackupReq::HeaderLength + 
01422              (i * StartBackupReq::TableTriggerLength), JBB);
01423 }
01424 
01425 void
01426 Backup::execSTART_BACKUP_REF(Signal* signal)
01427 {
01428   jamEntry();
01429 
01430   StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr();
01431   const Uint32 ptrI = ref->backupPtr;
01432   //const Uint32 backupId = ref->backupId;
01433   const Uint32 signalNo = ref->signalNo;
01434   const Uint32 nodeId = ref->nodeId;
01435 
01436   BackupRecordPtr ptr;
01437   c_backupPool.getPtr(ptr, ptrI);
01438 
01439   ptr.p->setErrorCode(ref->errorCode);
01440   startBackupReply(signal, ptr, nodeId, signalNo);
01441 }
01442 
01443 void
01444 Backup::execSTART_BACKUP_CONF(Signal* signal)
01445 {
01446   jamEntry();
01447   
01448   StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr();
01449   const Uint32 ptrI = conf->backupPtr;
01450   //const Uint32 backupId = conf->backupId;
01451   const Uint32 signalNo = conf->signalNo;
01452   const Uint32 nodeId = refToNode(signal->senderBlockRef());
01453   
01454   BackupRecordPtr ptr;
01455   c_backupPool.getPtr(ptr, ptrI);
01456 
01457   startBackupReply(signal, ptr, nodeId, signalNo);
01458 }
01459 
01460 void
01461 Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, 
01462                          Uint32 nodeId, Uint32 signalNo)
01463 {
01464 
01465   CRASH_INSERTION((10004));
01466 
01467   ndbrequire(ptr.p->masterData.startBackup.signalNo == signalNo);
01468   if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) {
01469     jam();
01470     return;
01471   }
01472 
01473   if (ERROR_INSERTED(10026))
01474   {
01475     ptr.p->errorCode = 326;
01476   }
01477 
01478   if(ptr.p->checkError()){
01479     jam();
01480     masterAbort(signal, ptr);
01481     return;
01482   }
01483 
01484   TablePtr tabPtr;
01485   c_tablePool.getPtr(tabPtr, ptr.p->masterData.startBackup.tablePtr);
01486   for(Uint32 i = 0; i<StartBackupReq::MaxTableTriggers; i++) {
01487     jam();
01488     if(!ptr.p->tables.next(tabPtr)) {
01489       jam();
01490       break;
01491     }//if
01492   }//for
01493   
01494   if(tabPtr.i != RNIL) {
01495     jam();
01496     ptr.p->masterData.startBackup.signalNo++;
01497     sendStartBackup(signal, ptr, tabPtr);
01498     return;
01499   }
01500 
01501   sendAlterTrig(signal, ptr);
01502 }
01503 
01504 /*****************************************************************************
01505  * 
01506  * Master functionallity - Activate triggers
01507  *
01508  *****************************************************************************/
01509 void
01510 Backup::sendAlterTrig(Signal* signal, BackupRecordPtr ptr)
01511 {
01512   AlterTrigReq * req =(AlterTrigReq *)signal->getDataPtrSend();
01513   
01514   ptr.p->masterData.gsn = GSN_ALTER_TRIG_REQ;
01515   ptr.p->masterData.sendCounter = 0;
01516   
01517   req->setUserRef(reference());
01518   req->setConnectionPtr(ptr.i);
01519   req->setRequestType(AlterTrigReq::RT_USER);
01520   req->setTriggerInfo(0);       // not used on ALTER via DICT
01521   req->setOnline(true);
01522   req->setReceiverRef(reference());
01523 
01524   TablePtr tabPtr;
01525 
01526   if (ptr.p->masterData.alterTrig.tableId == RNIL) {
01527     jam();
01528     ptr.p->tables.first(tabPtr);
01529   } else {
01530     jam();
01531     ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.alterTrig.tableId));
01532     ptr.p->tables.next(tabPtr);
01533   }//if
01534   if (tabPtr.i != RNIL) {
01535     jam();
01536     ptr.p->masterData.alterTrig.tableId = tabPtr.p->tableId;
01537     req->setTableId(tabPtr.p->tableId);
01538 
01539     req->setTriggerId(tabPtr.p->triggerIds[0]);
01540     sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ, 
01541                signal, AlterTrigReq::SignalLength, JBB);
01542     
01543     req->setTriggerId(tabPtr.p->triggerIds[1]);
01544     sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ, 
01545                signal, AlterTrigReq::SignalLength, JBB);
01546 
01547     req->setTriggerId(tabPtr.p->triggerIds[2]);
01548     sendSignal(DBDICT_REF, GSN_ALTER_TRIG_REQ, 
01549                signal, AlterTrigReq::SignalLength, JBB);
01550 
01551     ptr.p->masterData.sendCounter += 3;
01552     return;
01553   }//if
01554   ptr.p->masterData.alterTrig.tableId = RNIL;
01555 
01559   ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
01560   ptr.p->masterData.waitGCP.startBackup = true;
01561   
01562   WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend();
01563   waitGCPReq->senderRef = reference();
01564   waitGCPReq->senderData = ptr.i;
01565   waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
01566   sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, 
01567              WaitGCPReq::SignalLength,JBB);
01568 }
01569 
01570 void
01571 Backup::execALTER_TRIG_CONF(Signal* signal)
01572 {
01573   jamEntry();
01574 
01575   AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtr();
01576   const Uint32 ptrI = conf->getConnectionPtr();
01577   
01578   BackupRecordPtr ptr;
01579   c_backupPool.getPtr(ptr, ptrI);
01580   
01581   alterTrigReply(signal, ptr);
01582 }
01583 
01584 void
01585 Backup::execALTER_TRIG_REF(Signal* signal)
01586 {
01587   jamEntry();
01588 
01589   AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtr();
01590   const Uint32 ptrI = ref->getConnectionPtr();
01591   
01592   BackupRecordPtr ptr;
01593   c_backupPool.getPtr(ptr, ptrI);
01594 
01595   ptr.p->setErrorCode(ref->getErrorCode());
01596   
01597   alterTrigReply(signal, ptr);
01598 }
01599 
01600 void
01601 Backup::alterTrigReply(Signal* signal, BackupRecordPtr ptr)
01602 {
01603 
01604   CRASH_INSERTION((10005));
01605 
01606   ndbrequire(ptr.p->masterRef == reference());
01607   ndbrequire(ptr.p->masterData.gsn == GSN_ALTER_TRIG_REQ);
01608   ndbrequire(ptr.p->masterData.sendCounter.done() == false);
01609 
01610   ptr.p->masterData.sendCounter--;
01611 
01612   if(ptr.p->masterData.sendCounter.done() == false){
01613     jam();
01614     return;
01615   }//if
01616 
01617   if(ptr.p->checkError()){
01618     jam();
01619     masterAbort(signal, ptr);
01620     return;
01621   }//if
01622 
01623   sendAlterTrig(signal, ptr);
01624 }
01625 
01626 void
01627 Backup::execWAIT_GCP_REF(Signal* signal)
01628 {
01629   jamEntry();
01630   
01631   CRASH_INSERTION((10006));
01632 
01633   WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr();
01634   const Uint32 ptrI = ref->senderData;
01635   
01636   BackupRecordPtr ptr;
01637   c_backupPool.getPtr(ptr, ptrI);
01638 
01639   ndbrequire(ptr.p->masterRef == reference());
01640   ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
01641 
01642   WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
01643   req->senderRef = reference();
01644   req->senderData = ptr.i;
01645   req->requestType = WaitGCPReq::CompleteForceStart;
01646   sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, 
01647              WaitGCPReq::SignalLength,JBB);
01648 }
01649 
01650 void
01651 Backup::execWAIT_GCP_CONF(Signal* signal){
01652   jamEntry();
01653 
01654   CRASH_INSERTION((10007));
01655 
01656   WaitGCPConf * conf = (WaitGCPConf*)signal->getDataPtr();
01657   const Uint32 ptrI = conf->senderData;
01658   const Uint32 gcp = conf->gcp;
01659   
01660   BackupRecordPtr ptr;
01661   c_backupPool.getPtr(ptr, ptrI);
01662   
01663   ndbrequire(ptr.p->masterRef == reference());
01664   ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
01665   
01666   if(ptr.p->checkError()) {
01667     jam();
01668     masterAbort(signal, ptr);
01669     return;
01670   }//if
01671   
01672   if(ptr.p->masterData.waitGCP.startBackup) {
01673     jam();
01674     CRASH_INSERTION((10008));
01675     ptr.p->startGCP = gcp;
01676     ptr.p->masterData.sendCounter= 0;
01677     ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ;
01678     nextFragment(signal, ptr);
01679     return;
01680   } else {
01681     jam();
01682     if(gcp >= ptr.p->startGCP + 3)
01683     {
01684       CRASH_INSERTION((10009));
01685       ptr.p->stopGCP = gcp;
01686       sendDropTrig(signal, ptr); // regular dropping of triggers
01687       return;
01688     }//if
01689     
01693     WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
01694     req->senderRef = reference();
01695     req->senderData = ptr.i;
01696     req->requestType = WaitGCPReq::CompleteForceStart;
01697     sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, 
01698                WaitGCPReq::SignalLength,JBB);
01699     return;
01700   }
01701 }
01702 
01703 /*****************************************************************************
01704  * 
01705  * Master functionallity - Backup fragment
01706  *
01707  *****************************************************************************/
01708 void
01709 Backup::nextFragment(Signal* signal, BackupRecordPtr ptr)
01710 {
01711   jam();
01712 
01713   BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtrSend();
01714   req->backupPtr = ptr.i;
01715   req->backupId = ptr.p->backupId;
01716 
01717   NodeBitmask nodes = ptr.p->nodes;
01718   Uint32 idleNodes = nodes.count();
01719   Uint32 saveIdleNodes = idleNodes;
01720   ndbrequire(idleNodes > 0);
01721 
01722   TablePtr tabPtr;
01723   ptr.p->tables.first(tabPtr);
01724   for(; tabPtr.i != RNIL && idleNodes > 0; ptr.p->tables.next(tabPtr)) {
01725     jam();
01726     FragmentPtr fragPtr;
01727     Array<Fragment> & frags = tabPtr.p->fragments;
01728     const Uint32 fragCount = frags.getSize();
01729     
01730     for(Uint32 i = 0; i<fragCount && idleNodes > 0; i++) {
01731       jam();
01732       tabPtr.p->fragments.getPtr(fragPtr, i);
01733       const Uint32 nodeId = fragPtr.p->node;
01734       if(fragPtr.p->scanning != 0) {
01735         jam();
01736         ndbrequire(nodes.get(nodeId));
01737         nodes.clear(nodeId);
01738         idleNodes--;
01739       } else if(fragPtr.p->scanned == 0 && nodes.get(nodeId)){
01740         jam();
01741         fragPtr.p->scanning = 1;
01742         nodes.clear(nodeId);
01743         idleNodes--;
01744         
01745         req->tableId = tabPtr.p->tableId;
01746         req->fragmentNo = i;
01747         req->count = 0;
01748 
01749         ptr.p->masterData.sendCounter++;
01750         const BlockReference ref = numberToRef(BACKUP, nodeId);
01751         sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal,
01752                    BackupFragmentReq::SignalLength, JBB);
01753       }//if
01754     }//for
01755   }//for
01756   
01757   if(idleNodes != saveIdleNodes){
01758     jam();
01759     return;
01760   }//if
01761 
01765   {
01766     ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
01767     ptr.p->masterData.waitGCP.startBackup = false;
01768     
01769     WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
01770     req->senderRef = reference();
01771     req->senderData = ptr.i;
01772     req->requestType = WaitGCPReq::CompleteForceStart;
01773     sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, 
01774                WaitGCPReq::SignalLength, JBB);
01775   }
01776 }
01777 
01778 void
01779 Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
01780 {
01781   jamEntry();
01782 
01783   CRASH_INSERTION((10010));
01784   
01785   BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtr();
01786   const Uint32 ptrI = conf->backupPtr;
01787   //const Uint32 backupId = conf->backupId;
01788   const Uint32 tableId = conf->tableId;
01789   const Uint32 fragmentNo = conf->fragmentNo;
01790   const Uint32 nodeId = refToNode(signal->senderBlockRef());
01791   const Uint32 noOfBytes = conf->noOfBytes;
01792   const Uint32 noOfRecords = conf->noOfRecords;
01793   
01794   BackupRecordPtr ptr;
01795   c_backupPool.getPtr(ptr, ptrI);
01796 
01797   ptr.p->noOfBytes += noOfBytes;
01798   ptr.p->noOfRecords += noOfRecords;
01799   ptr.p->masterData.sendCounter--;
01800 
01801   TablePtr tabPtr;
01802   ndbrequire(findTable(ptr, tabPtr, tableId));
01803 
01804   FragmentPtr fragPtr;
01805   tabPtr.p->fragments.getPtr(fragPtr, fragmentNo);
01806 
01807   ndbrequire(fragPtr.p->scanned == 0);
01808   ndbrequire(fragPtr.p->scanning == 1);
01809   ndbrequire(fragPtr.p->node == nodeId);
01810 
01811   fragPtr.p->scanned = 1;
01812   fragPtr.p->scanning = 0;
01813 
01814   if (ERROR_INSERTED(10028)) 
01815   {
01816     ptr.p->errorCode = 328;
01817   }
01818 
01819   if(ptr.p->checkError()) 
01820   {
01821     if(ptr.p->masterData.sendCounter.done())
01822     {
01823       jam();
01824       masterAbort(signal, ptr);
01825       return;
01826     }//if
01827   }
01828   else
01829   {
01830     nextFragment(signal, ptr);
01831   }
01832 }
01833 
01834 void
01835 Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
01836 {
01837   jamEntry();
01838 
01839   CRASH_INSERTION((10011));
01840 
01841   BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
01842   const Uint32 ptrI = ref->backupPtr;
01843   //const Uint32 backupId = ref->backupId;
01844   const Uint32 nodeId = ref->nodeId;
01845   
01846   BackupRecordPtr ptr;
01847   c_backupPool.getPtr(ptr, ptrI);
01848 
01849   TablePtr tabPtr;
01850   ptr.p->tables.first(tabPtr);
01851   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
01852     jam();
01853     FragmentPtr fragPtr;
01854     Array<Fragment> & frags = tabPtr.p->fragments;
01855     const Uint32 fragCount = frags.getSize();
01856     
01857     for(Uint32 i = 0; i<fragCount; i++) {
01858       jam();
01859       tabPtr.p->fragments.getPtr(fragPtr, i);
01860         if(fragPtr.p->scanning != 0 && nodeId == fragPtr.p->node) 
01861       {
01862         jam();
01863         ndbrequire(fragPtr.p->scanned == 0);
01864         fragPtr.p->scanned = 1;
01865         fragPtr.p->scanning = 0;
01866         goto done;
01867       }
01868     }
01869   }
01870   ndbrequire(false);
01871 
01872 done:
01873   ptr.p->masterData.sendCounter--;
01874   ptr.p->setErrorCode(ref->errorCode);
01875   
01876   if(ptr.p->masterData.sendCounter.done())
01877   {
01878     jam();
01879     masterAbort(signal, ptr);
01880     return;
01881   }//if
01882   
01883   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
01884   ord->backupId = ptr.p->backupId;
01885   ord->backupPtr = ptr.i;
01886   ord->requestType = AbortBackupOrd::LogBufferFull;
01887   ord->senderData= ptr.i;
01888   execABORT_BACKUP_ORD(signal);
01889 }
01890 
01891 /*****************************************************************************
01892  * 
01893  * Master functionallity - Drop triggers
01894  *
01895  *****************************************************************************/
01896 
01897 void
01898 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr)
01899 {
01900   TablePtr tabPtr;
01901   if (ptr.p->masterData.dropTrig.tableId == RNIL) {
01902     jam();
01903     ptr.p->tables.first(tabPtr);
01904   } else {
01905     jam();
01906     ndbrequire(findTable(ptr, tabPtr, ptr.p->masterData.dropTrig.tableId));
01907     ptr.p->tables.next(tabPtr);
01908   }//if
01909   if (tabPtr.i != RNIL) {
01910     jam();
01911     sendDropTrig(signal, ptr, tabPtr);
01912   } else {
01913     jam();
01914     ptr.p->masterData.dropTrig.tableId = RNIL;
01915 
01916     sendStopBackup(signal, ptr);
01917   }//if
01918 }
01919 
01920 void
01921 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
01922 {
01923   jam();
01924   DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend();
01925 
01926   ptr.p->masterData.gsn = GSN_DROP_TRIG_REQ;
01927   ptr.p->masterData.sendCounter = 0;
01928     
01929   req->setConnectionPtr(ptr.i);
01930   req->setUserRef(reference()); // Sending to myself
01931   req->setRequestType(DropTrigReq::RT_USER);
01932   req->setIndexId(RNIL);
01933   req->setTriggerInfo(0);       // not used on DROP via DICT
01934 
01935   char triggerName[MAX_TAB_NAME_SIZE];
01936   Uint32 nameBuffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];  // SP string
01937   LinearWriter w(nameBuffer, sizeof(nameBuffer) >> 2);
01938   LinearSectionPtr lsPtr[3];
01939   
01940   ptr.p->masterData.dropTrig.tableId = tabPtr.p->tableId;
01941   req->setTableId(tabPtr.p->tableId);
01942 
01943   for (int i = 0; i < 3; i++) {
01944     Uint32 id = tabPtr.p->triggerIds[i];
01945     req->setTriggerId(id);
01946     if (id != ILLEGAL_TRIGGER_ID) {
01947       sendSignal(DBDICT_REF, GSN_DROP_TRIG_REQ, 
01948                  signal, DropTrigReq::SignalLength, JBB);
01949     } else {
01950       BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
01951                ptr.p->backupId, tabPtr.p->tableId);
01952       w.reset();
01953       w.add(CreateTrigReq::TriggerNameKey, triggerName);
01954       lsPtr[0].p = nameBuffer;
01955       lsPtr[0].sz = w.getWordsUsed();
01956       sendSignal(DBDICT_REF, GSN_DROP_TRIG_REQ, 
01957                  signal, DropTrigReq::SignalLength, JBB, lsPtr, 1);
01958     }
01959     ptr.p->masterData.sendCounter ++;
01960   }
01961 }
01962 
01963 void
01964 Backup::execDROP_TRIG_REF(Signal* signal)
01965 {
01966   jamEntry();
01967 
01968   DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
01969   const Uint32 ptrI = ref->getConnectionPtr();
01970   
01971   BackupRecordPtr ptr;
01972   c_backupPool.getPtr(ptr, ptrI);
01973  
01974   //ndbrequire(ref->getErrorCode() == DropTrigRef::NoSuchTrigger);
01975   dropTrigReply(signal, ptr);
01976 }
01977 
01978 void
01979 Backup::execDROP_TRIG_CONF(Signal* signal)
01980 {
01981   jamEntry();
01982   
01983   DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
01984   const Uint32 ptrI = conf->getConnectionPtr();
01985   
01986   BackupRecordPtr ptr;
01987   c_backupPool.getPtr(ptr, ptrI);
01988   
01989   dropTrigReply(signal, ptr);
01990 }
01991 
01992 void
01993 Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr)
01994 {
01995 
01996   CRASH_INSERTION((10012));
01997 
01998   ndbrequire(ptr.p->masterRef == reference());
01999   ndbrequire(ptr.p->masterData.gsn == GSN_DROP_TRIG_REQ);
02000   ndbrequire(ptr.p->masterData.sendCounter.done() == false);
02001   
02002   ptr.p->masterData.sendCounter--;
02003   if(ptr.p->masterData.sendCounter.done() == false){
02004     jam();
02005     return;
02006   }//if
02007   
02008   sendDropTrig(signal, ptr); // recursive next
02009 }
02010 
02011 /*****************************************************************************
02012  * 
02013  * Master functionallity - Stop backup
02014  *
02015  *****************************************************************************/
02016 void
02017 Backup::execSTOP_BACKUP_REF(Signal* signal)
02018 {
02019   jamEntry();
02020 
02021   StopBackupRef* ref = (StopBackupRef*)signal->getDataPtr();
02022   const Uint32 ptrI = ref->backupPtr;
02023   //const Uint32 backupId = ref->backupId;
02024   const Uint32 nodeId = ref->nodeId;
02025   
02026   BackupRecordPtr ptr;
02027   c_backupPool.getPtr(ptr, ptrI);
02028 
02029   ptr.p->setErrorCode(ref->errorCode);
02030   stopBackupReply(signal, ptr, nodeId);
02031 }
02032 
02033 void
02034 Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr)
02035 {
02036   jam();
02037 
02038   StopBackupReq* stop = (StopBackupReq*)signal->getDataPtrSend();
02039   stop->backupPtr = ptr.i;
02040   stop->backupId = ptr.p->backupId;
02041   stop->startGCP = ptr.p->startGCP;
02042   stop->stopGCP = ptr.p->stopGCP;
02043 
02044   ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
02045   ptr.p->masterData.sendCounter = ptr.p->nodes;
02046   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
02047   sendSignal(rg, GSN_STOP_BACKUP_REQ, signal, 
02048              StopBackupReq::SignalLength, JBB);
02049 }
02050 
02051 void
02052 Backup::execSTOP_BACKUP_CONF(Signal* signal)
02053 {
02054   jamEntry();
02055   
02056   StopBackupConf* conf = (StopBackupConf*)signal->getDataPtr();
02057   const Uint32 ptrI = conf->backupPtr;
02058   //const Uint32 backupId = conf->backupId;
02059   const Uint32 nodeId = refToNode(signal->senderBlockRef());
02060   
02061   BackupRecordPtr ptr;
02062   c_backupPool.getPtr(ptr, ptrI);
02063 
02064   ptr.p->noOfLogBytes += conf->noOfLogBytes;
02065   ptr.p->noOfLogRecords += conf->noOfLogRecords;
02066   
02067   stopBackupReply(signal, ptr, nodeId);
02068 }
02069 
02070 void
02071 Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
02072 {
02073   CRASH_INSERTION((10013));
02074 
02075   if (!haveAllSignals(ptr, GSN_STOP_BACKUP_REQ, nodeId)) {
02076     jam();
02077     return;
02078   }
02079 
02080   sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete);
02081   
02082   if(!ptr.p->checkError())
02083   {
02084     BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
02085     rep->backupId = ptr.p->backupId;
02086     rep->senderData = ptr.p->clientData;
02087     rep->startGCP = ptr.p->startGCP;
02088     rep->stopGCP = ptr.p->stopGCP;
02089     rep->noOfBytes = ptr.p->noOfBytes;
02090     rep->noOfRecords = ptr.p->noOfRecords;
02091     rep->noOfLogBytes = ptr.p->noOfLogBytes;
02092     rep->noOfLogRecords = ptr.p->noOfLogRecords;
02093     rep->nodes = ptr.p->nodes;
02094     sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
02095                BackupCompleteRep::SignalLength, JBB);
02096     
02097     signal->theData[0] = NDB_LE_BackupCompleted;
02098     signal->theData[1] = ptr.p->clientRef;
02099     signal->theData[2] = ptr.p->backupId;
02100     signal->theData[3] = ptr.p->startGCP;
02101     signal->theData[4] = ptr.p->stopGCP;
02102     signal->theData[5] = ptr.p->noOfBytes;
02103     signal->theData[6] = ptr.p->noOfRecords;
02104     signal->theData[7] = ptr.p->noOfLogBytes;
02105     signal->theData[8] = ptr.p->noOfLogRecords;
02106     ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9);
02107     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 9+NdbNodeBitmask::Size, JBB);
02108   }
02109   else
02110   {
02111     masterAbort(signal, ptr);
02112   }
02113 }
02114 
02115 /*****************************************************************************
02116  * 
02117  * Master functionallity - Abort backup
02118  *
02119  *****************************************************************************/
02120 void
02121 Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
02122 {
02123   jam();
02124 #ifdef DEBUG_ABORT
02125   ndbout_c("************ masterAbort");
02126 #endif
02127   if(ptr.p->masterData.errorCode != 0)
02128   {
02129     jam();
02130     return;
02131   }
02132 
02133   BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
02134   rep->backupId = ptr.p->backupId;
02135   rep->senderData = ptr.p->clientData;
02136   rep->reason = ptr.p->errorCode;
02137   sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, 
02138              BackupAbortRep::SignalLength, JBB);
02139   
02140   signal->theData[0] = NDB_LE_BackupAborted;
02141   signal->theData[1] = ptr.p->clientRef;
02142   signal->theData[2] = ptr.p->backupId;
02143   signal->theData[3] = ptr.p->errorCode;
02144   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
02145 
02146   ndbrequire(ptr.p->errorCode);
02147   ptr.p->masterData.errorCode = ptr.p->errorCode;
02148 
02149   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
02150   ord->backupId = ptr.p->backupId;
02151   ord->backupPtr = ptr.i;
02152   ord->senderData= ptr.i;
02153   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
02154   
02155   switch(ptr.p->masterData.gsn){
02156   case GSN_DEFINE_BACKUP_REQ:
02157     ord->requestType = AbortBackupOrd::BackupFailure;
02158     sendSignal(rg, GSN_ABORT_BACKUP_ORD, signal, 
02159                AbortBackupOrd::SignalLength, JBB);
02160     return;
02161   case GSN_CREATE_TRIG_REQ:
02162   case GSN_START_BACKUP_REQ:
02163   case GSN_ALTER_TRIG_REQ:
02164   case GSN_WAIT_GCP_REQ:
02165   case GSN_BACKUP_FRAGMENT_REQ:
02166     jam();
02167     ptr.p->stopGCP= ptr.p->startGCP + 1;
02168     sendDropTrig(signal, ptr); // dropping due to error
02169     return;
02170   case GSN_UTIL_SEQUENCE_REQ:
02171   case GSN_UTIL_LOCK_REQ:
02172   case GSN_DROP_TRIG_REQ:
02173     ndbrequire(false);
02174     return;
02175   case GSN_STOP_BACKUP_REQ:
02176     return;
02177   }
02178 }
02179 
02180 void
02181 Backup::abort_scan(Signal * signal, BackupRecordPtr ptr)
02182 {
02183   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
02184   ord->backupId = ptr.p->backupId;
02185   ord->backupPtr = ptr.i;
02186   ord->senderData= ptr.i;
02187   ord->requestType = AbortBackupOrd::AbortScan;
02188 
02189   TablePtr tabPtr;
02190   ptr.p->tables.first(tabPtr);
02191   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
02192     jam();
02193     FragmentPtr fragPtr;
02194     Array<Fragment> & frags = tabPtr.p->fragments;
02195     const Uint32 fragCount = frags.getSize();
02196     
02197     for(Uint32 i = 0; i<fragCount; i++) {
02198       jam();
02199       tabPtr.p->fragments.getPtr(fragPtr, i);
02200       const Uint32 nodeId = fragPtr.p->node;
02201       if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) {
02202         jam();
02203         
02204         const BlockReference ref = numberToRef(BACKUP, nodeId);
02205         sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal,
02206                    AbortBackupOrd::SignalLength, JBB);
02207         
02208       }
02209     }
02210   }
02211 }
02212 
02213 /*****************************************************************************
02214  * 
02215  * Slave functionallity: Define Backup 
02216  *
02217  *****************************************************************************/
02218 void
02219 Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode)
02220 {
02221   ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
02222   ptr.p->setErrorCode(errCode);
02223   ndbrequire(ptr.p->errorCode != 0);
02224   
02225   DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
02226   ref->backupId = ptr.p->backupId;
02227   ref->backupPtr = ptr.i;
02228   ref->errorCode = ptr.p->errorCode;
02229   ref->nodeId = getOwnNodeId();
02230   sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal, 
02231              DefineBackupRef::SignalLength, JBB);
02232 }
02233 
02234 void
02235 Backup::execDEFINE_BACKUP_REQ(Signal* signal)
02236 {
02237   jamEntry();
02238 
02239   DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr();
02240   
02241   BackupRecordPtr ptr;
02242   const Uint32 ptrI = req->backupPtr;
02243   const Uint32 backupId = req->backupId;
02244   const BlockReference senderRef = req->senderRef;
02245 
02246   if(senderRef == reference()){
02250     jam();
02251     c_backupPool.getPtr(ptr, ptrI);
02252   } else { // from other node
02253     jam();
02254 #ifdef DEBUG_ABORT
02255     dumpUsedResources();
02256 #endif
02257     if(!c_backups.seizeId(ptr, ptrI)) {
02258       jam();
02259       ndbrequire(false); // If master has succeeded slave should succed
02260     }//if
02261   }//if
02262 
02263   CRASH_INSERTION((10014));
02264   
02265   ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ;
02266   ptr.p->slaveState.forceState(INITIAL);
02267   ptr.p->slaveState.setState(DEFINING);
02268   ptr.p->errorCode = 0;
02269   ptr.p->clientRef = req->clientRef;
02270   ptr.p->clientData = req->clientData;
02271   ptr.p->masterRef = senderRef;
02272   ptr.p->nodes = req->nodes;
02273   ptr.p->backupId = backupId;
02274   ptr.p->backupKey[0] = req->backupKey[0];
02275   ptr.p->backupKey[1] = req->backupKey[1];
02276   ptr.p->backupDataLen = req->backupDataLen;
02277   ptr.p->masterData.dropTrig.tableId = RNIL;
02278   ptr.p->masterData.alterTrig.tableId = RNIL;
02279   ptr.p->masterData.errorCode = 0;
02280   ptr.p->noOfBytes = 0;
02281   ptr.p->noOfRecords = 0;
02282   ptr.p->noOfLogBytes = 0;
02283   ptr.p->noOfLogRecords = 0;
02284   ptr.p->currGCP = 0;
02285   
02289   BackupFilePtr files[3];
02290   Uint32 noOfPages[] = {
02291     NO_OF_PAGES_META_FILE,
02292     2,   // 32k
02293     0    // 3M
02294   };
02295   const Uint32 maxInsert[] = {
02296     2048,  // Temporarily to solve TR515
02297     //25,      // 100 bytes
02298     2048,    // 4k
02299     16*3000, // Max 16 tuples
02300   };
02301   Uint32 minWrite[] = {
02302     8192,
02303     8192,
02304     32768
02305   };
02306   Uint32 maxWrite[] = {
02307     8192,
02308     8192,
02309     32768
02310   };
02311   
02312   minWrite[1] = c_defaults.m_minWriteSize;
02313   maxWrite[1] = c_defaults.m_maxWriteSize;
02314   noOfPages[1] = (c_defaults.m_logBufferSize + sizeof(Page32) - 1) / 
02315     sizeof(Page32);
02316   minWrite[2] = c_defaults.m_minWriteSize;
02317   maxWrite[2] = c_defaults.m_maxWriteSize;
02318   noOfPages[2] = (c_defaults.m_dataBufferSize + sizeof(Page32) - 1) / 
02319     sizeof(Page32);
02320   
02321   for(Uint32 i = 0; i<3; i++) {
02322     jam();
02323     if(!ptr.p->files.seize(files[i])) {
02324       jam();
02325       defineBackupRef(signal, ptr, 
02326                       DefineBackupRef::FailedToAllocateFileRecord);
02327       return;
02328     }//if
02329 
02330     files[i].p->tableId = RNIL;
02331     files[i].p->backupPtr = ptr.i;
02332     files[i].p->filePointer = RNIL;
02333     files[i].p->fileClosing = 0;
02334     files[i].p->fileOpened = 0;
02335     files[i].p->fileRunning = 0;    
02336     files[i].p->scanRunning = 0;
02337     files[i].p->errorCode = 0;
02338     
02339     if(files[i].p->pages.seize(noOfPages[i]) == false) {
02340       jam();
02341       DEBUG_OUT("Failed to seize " << noOfPages[i] << " pages");
02342       defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateBuffers);
02343       return;
02344     }//if
02345     Page32Ptr pagePtr;
02346     files[i].p->pages.getPtr(pagePtr, 0);
02347     
02348     const char * msg = files[i].p->
02349       operation.dataBuffer.setup((Uint32*)pagePtr.p, 
02350                                  noOfPages[i] * (sizeof(Page32) >> 2),
02351                                  128,
02352                                  minWrite[i] >> 2,
02353                                  maxWrite[i] >> 2,
02354                                  maxInsert[i]);
02355     if(msg != 0) {
02356       jam();
02357       defineBackupRef(signal, ptr, DefineBackupRef::FailedToSetupFsBuffers);
02358       return;
02359     }//if
02360   }//for
02361   files[0].p->fileType = BackupFormat::CTL_FILE;
02362   files[1].p->fileType = BackupFormat::LOG_FILE;
02363   files[2].p->fileType = BackupFormat::DATA_FILE;
02364   
02365   ptr.p->ctlFilePtr = files[0].i;
02366   ptr.p->logFilePtr = files[1].i;
02367   ptr.p->dataFilePtr = files[2].i;
02368   
02369   if (!verifyNodesAlive(ptr, ptr.p->nodes)) {
02370     jam();
02371     defineBackupRef(signal, ptr, DefineBackupRef::Undefined);
02372     return;
02373   }//if
02374   if (ERROR_INSERTED(10027)) {
02375     jam();
02376     defineBackupRef(signal, ptr, 327);
02377     return;
02378   }//if
02379 
02380   if(ptr.p->backupDataLen == 0) {
02381     jam();
02382     backupAllData(signal, ptr);
02383     return;
02384   }//if
02385   
02389   ndbrequire(0);
02390 }
02391 
02392 void
02393 Backup::backupAllData(Signal* signal, BackupRecordPtr ptr)
02394 {
02398   ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend();
02399   req->senderRef = reference();
02400   req->senderData = ptr.i;
02401   req->requestData = 0;
02402   sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal, 
02403              ListTablesReq::SignalLength, JBB);
02404 }
02405 
02406 void
02407 Backup::execLIST_TABLES_CONF(Signal* signal)
02408 {
02409   jamEntry();
02410   
02411   ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr();
02412 
02413   BackupRecordPtr ptr;
02414   c_backupPool.getPtr(ptr, conf->senderData);
02415   
02416   const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
02417   for(unsigned int i = 0; i<len; i++) {
02418     jam();
02419     Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
02420     Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
02421     if (!DictTabInfo::isTable(tableType) && !DictTabInfo::isIndex(tableType)){
02422       jam();
02423       continue;
02424     }//if
02425     TablePtr tabPtr;
02426     ptr.p->tables.seize(tabPtr);
02427     if(tabPtr.i == RNIL) {
02428       jam();
02429       defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateTables);
02430       return;
02431     }//if
02432     tabPtr.p->tableId = tableId;
02433     tabPtr.p->tableType = tableType;
02434   }//for
02435   
02436   if(len == ListTablesConf::DataLength) {
02437     jam();
02441     return;
02442   }//if
02443 
02447   openFiles(signal, ptr);
02448 }
02449 
02450 void
02451 Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
02452 {
02453   jam();
02454 
02455   BackupFilePtr filePtr;
02456 
02457   FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
02458   req->userReference = reference();
02459   req->fileFlags = 
02460     FsOpenReq::OM_WRITEONLY | 
02461     FsOpenReq::OM_TRUNCATE |
02462     FsOpenReq::OM_CREATE | 
02463     FsOpenReq::OM_APPEND |
02464     FsOpenReq::OM_SYNC;
02465   FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
02466   
02470   c_backupFilePool.getPtr(filePtr, ptr.p->ctlFilePtr);
02471   ndbrequire(filePtr.p->fileRunning == 0);
02472   filePtr.p->fileRunning = 1;
02473 
02474   req->userPointer = filePtr.i;
02475   FsOpenReq::setVersion(req->fileNumber, 2);
02476   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
02477   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
02478   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
02479   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
02480 
02484   c_backupFilePool.getPtr(filePtr, ptr.p->logFilePtr);
02485   ndbrequire(filePtr.p->fileRunning == 0);
02486   filePtr.p->fileRunning = 1;
02487   
02488   req->userPointer = filePtr.i;
02489   FsOpenReq::setVersion(req->fileNumber, 2);
02490   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_LOG);
02491   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
02492   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
02493   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
02494 
02498   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
02499   ndbrequire(filePtr.p->fileRunning == 0);
02500   filePtr.p->fileRunning = 1;
02501 
02502   req->userPointer = filePtr.i;
02503   FsOpenReq::setVersion(req->fileNumber, 2);
02504   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
02505   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
02506   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
02507   FsOpenReq::v2_setCount(req->fileNumber, 0);
02508   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
02509 }
02510 
02511 void
02512 Backup::execFSOPENREF(Signal* signal)
02513 {
02514   jamEntry();
02515 
02516   FsRef * ref = (FsRef *)signal->getDataPtr();
02517   
02518   const Uint32 userPtr = ref->userPointer;
02519   
02520   BackupFilePtr filePtr;
02521   c_backupFilePool.getPtr(filePtr, userPtr);
02522   
02523   BackupRecordPtr ptr;
02524   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
02525   ptr.p->setErrorCode(ref->errorCode);
02526   openFilesReply(signal, ptr, filePtr);
02527 }
02528 
02529 void
02530 Backup::execFSOPENCONF(Signal* signal)
02531 {
02532   jamEntry();
02533   
02534   FsConf * conf = (FsConf *)signal->getDataPtr();
02535   
02536   const Uint32 userPtr = conf->userPointer;
02537   const Uint32 filePointer = conf->filePointer;
02538   
02539   BackupFilePtr filePtr;
02540   c_backupFilePool.getPtr(filePtr, userPtr);
02541   filePtr.p->filePointer = filePointer; 
02542   
02543   BackupRecordPtr ptr;
02544   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
02545 
02546   ndbrequire(filePtr.p->fileOpened == 0);
02547   filePtr.p->fileOpened = 1;
02548   openFilesReply(signal, ptr, filePtr);
02549 }
02550 
02551 void
02552 Backup::openFilesReply(Signal* signal, 
02553                        BackupRecordPtr ptr, BackupFilePtr filePtr)
02554 {
02555   jam();
02556 
02560   ndbrequire(filePtr.p->fileRunning == 1);
02561   filePtr.p->fileRunning = 0;
02562   
02566   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr)) 
02567   {
02568     jam();
02569     if(filePtr.p->fileRunning == 1) {
02570       jam();
02571       return;
02572     }//if
02573   }//for
02574 
02578   if(ptr.p->checkError()) {
02579     jam();
02580     defineBackupRef(signal, ptr);
02581     return;
02582   }//if
02583 
02587   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
02588   if(!insertFileHeader(BackupFormat::CTL_FILE, ptr.p, filePtr.p)) {
02589     jam();
02590     defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
02591     return;
02592   }//if
02593 
02594   ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
02595   if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
02596     jam();
02597     defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
02598     return;
02599   }//if
02600 
02601   ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
02602   if(!insertFileHeader(BackupFormat::DATA_FILE, ptr.p, filePtr.p)) {
02603     jam();
02604     defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
02605     return;
02606   }//if
02607 
02611   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
02612   filePtr.p->fileRunning = 1;
02613   
02614   signal->theData[0] = BackupContinueB::START_FILE_THREAD;
02615   signal->theData[1] = ptr.p->ctlFilePtr;
02616   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
02617 
02621   FsBuffer & buf = filePtr.p->operation.dataBuffer;
02622 
02623   const Uint32 sz = 
02624     (sizeof(BackupFormat::CtlFile::TableList) >> 2) +
02625     ptr.p->tables.noOfElements() - 1;
02626   
02627   Uint32 * dst;
02628   ndbrequire(sz < buf.getMaxWrite());
02629   if(!buf.getWritePtr(&dst, sz)) {
02630     jam();
02631     defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertTableList);
02632     return;
02633   }//if
02634   
02635   BackupFormat::CtlFile::TableList* tl = 
02636     (BackupFormat::CtlFile::TableList*)dst;
02637   tl->SectionType   = htonl(BackupFormat::TABLE_LIST);
02638   tl->SectionLength = htonl(sz);
02639 
02640   TablePtr tabPtr;
02641   Uint32 count = 0;
02642   for(ptr.p->tables.first(tabPtr); 
02643       tabPtr.i != RNIL;
02644       ptr.p->tables.next(tabPtr)){
02645     jam();
02646     tl->TableIds[count] = htonl(tabPtr.p->tableId);
02647     count++;
02648   }//for
02649   
02650   buf.updateWritePtr(sz);
02651   
02655   ndbrequire(ptr.p->tables.first(tabPtr));
02656 
02657   signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
02658   signal->theData[1] = ptr.i;
02659   signal->theData[2] = tabPtr.i;
02660   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
02661   return;
02662 }
02663 
02664 bool
02665 Backup::insertFileHeader(BackupFormat::FileType ft, 
02666                          BackupRecord * ptrP,
02667                          BackupFile * filePtrP){
02668   FsBuffer & buf = filePtrP->operation.dataBuffer;
02669 
02670   const Uint32 sz = sizeof(BackupFormat::FileHeader) >> 2;
02671 
02672   Uint32 * dst;
02673   ndbrequire(sz < buf.getMaxWrite());
02674   if(!buf.getWritePtr(&dst, sz)) {
02675     jam();
02676     return false;
02677   }//if
02678   
02679   BackupFormat::FileHeader* header = (BackupFormat::FileHeader*)dst;
02680   ndbrequire(sizeof(header->Magic) == sizeof(BACKUP_MAGIC));
02681   memcpy(header->Magic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC));
02682   header->NdbVersion    = htonl(NDB_VERSION);
02683   header->SectionType   = htonl(BackupFormat::FILE_HEADER);
02684   header->SectionLength = htonl(sz - 3);
02685   header->FileType      = htonl(ft);
02686   header->BackupId      = htonl(ptrP->backupId);
02687   header->BackupKey_0   = htonl(ptrP->backupKey[0]);
02688   header->BackupKey_1   = htonl(ptrP->backupKey[1]);
02689   header->ByteOrder     = 0x12345678;
02690   
02691   buf.updateWritePtr(sz);
02692   return true;
02693 }
02694 
02695 void
02696 Backup::execGET_TABINFOREF(Signal* signal)
02697 {
02698   GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr();
02699   
02700   const Uint32 senderData = ref->senderData;
02701   BackupRecordPtr ptr;
02702   c_backupPool.getPtr(ptr, senderData);
02703 
02704   defineBackupRef(signal, ptr, ref->errorCode);
02705 }
02706 
02707 void
02708 Backup::execGET_TABINFO_CONF(Signal* signal)
02709 {
02710   jamEntry();
02711 
02712   if(!assembleFragments(signal)) {
02713     jam();
02714     return;
02715   }//if
02716 
02717   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
02718   //const Uint32 senderRef = info->senderRef;
02719   const Uint32 len = conf->totalLen;
02720   const Uint32 senderData = conf->senderData;
02721 
02722   BackupRecordPtr ptr;
02723   c_backupPool.getPtr(ptr, senderData);
02724   
02725   SegmentedSectionPtr dictTabInfoPtr;
02726   signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
02727   ndbrequire(dictTabInfoPtr.sz == len);
02728 
02732   const Uint32 noPages = (len + sizeof(Page32) - 1) / sizeof(Page32);
02733   if(ptr.p->pages.getSize() < noPages) {
02734     jam();
02735     ptr.p->pages.release();
02736     if(ptr.p->pages.seize(noPages) == false) {
02737       jam();
02738       ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
02739       ndbrequire(false);
02740       releaseSections(signal);
02741       defineBackupRef(signal, ptr);
02742       return;
02743     }//if
02744   }//if
02745   
02746   BackupFilePtr filePtr;
02747   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
02748   FsBuffer & buf = filePtr.p->operation.dataBuffer;
02749   { // Write into ctl file
02750     Uint32* dst, dstLen = len + 2;
02751     if(!buf.getWritePtr(&dst, dstLen)) {
02752       jam();
02753       ndbrequire(false);
02754       ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
02755       releaseSections(signal);
02756       defineBackupRef(signal, ptr);
02757       return;
02758     }//if
02759     if(dst != 0) {
02760       jam();
02761 
02762       BackupFormat::CtlFile::TableDescription * desc = 
02763         (BackupFormat::CtlFile::TableDescription*)dst;
02764       desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION);
02765       desc->SectionLength = htonl(len + 2);
02766       dst += 2;
02767 
02768       copy(dst, dictTabInfoPtr);
02769       buf.updateWritePtr(dstLen);
02770     }//if
02771   }
02772   
02773   ndbrequire(ptr.p->pages.getSize() >= noPages);
02774   Page32Ptr pagePtr;
02775   ptr.p->pages.getPtr(pagePtr, 0);
02776   copy(&pagePtr.p->data[0], dictTabInfoPtr);
02777   releaseSections(signal);
02778   
02779   if(ptr.p->checkError()) {
02780     jam();
02781     defineBackupRef(signal, ptr);
02782     return;
02783   }//if
02784 
02785   TablePtr tabPtr = parseTableDescription(signal, ptr, len);
02786   if(tabPtr.i == RNIL) {
02787     jam();
02788     defineBackupRef(signal, ptr);
02789     return;
02790   }//if
02791 
02792   TablePtr tmp = tabPtr;
02793   ptr.p->tables.next(tabPtr);
02794   if(DictTabInfo::isIndex(tmp.p->tableType)){
02795     ptr.p->tables.release(tmp);
02796   }
02797   
02798   if(tabPtr.i == RNIL) {
02799     jam();
02800     
02801     ptr.p->pages.release();
02802     
02803     ndbrequire(ptr.p->tables.first(tabPtr));
02804     signal->theData[0] = RNIL;
02805     signal->theData[1] = tabPtr.p->tableId;
02806     signal->theData[2] = ptr.i;
02807     sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal, 3, JBB);
02808     return;
02809   }//if
02810 
02811   signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
02812   signal->theData[1] = ptr.i;
02813   signal->theData[2] = tabPtr.i;
02814   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
02815   return;
02816 }
02817 
02818 Backup::TablePtr
02819 Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
02820 {
02821 
02822   Page32Ptr pagePtr;
02823   ptr.p->pages.getPtr(pagePtr, 0);
02824   
02825   SimplePropertiesLinearReader it(&pagePtr.p->data[0], len);
02826   
02827   it.first();
02828   
02829   DictTabInfo::Table tmpTab; tmpTab.init();
02830   SimpleProperties::UnpackStatus stat;
02831   stat = SimpleProperties::unpack(it, &tmpTab, 
02832                                   DictTabInfo::TableMapping, 
02833                                   DictTabInfo::TableMappingSize, 
02834                                   true, true);
02835   ndbrequire(stat == SimpleProperties::Break);
02836   
02837   TablePtr tabPtr;
02838   ndbrequire(findTable(ptr, tabPtr, tmpTab.TableId));
02839   if(DictTabInfo::isIndex(tabPtr.p->tableType)){
02840     jam();
02841     return tabPtr;
02842   }
02843   
02847   tabPtr.p->frag_mask = RNIL;
02848 
02849   tabPtr.p->schemaVersion = tmpTab.TableVersion;
02850   tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
02851   tabPtr.p->noOfNull = 0;
02852   tabPtr.p->noOfVariable = 0; // Computed while iterating over attribs
02853   tabPtr.p->sz_FixedAttributes = 0; // Computed while iterating over attribs
02854   tabPtr.p->triggerIds[0] = ILLEGAL_TRIGGER_ID;
02855   tabPtr.p->triggerIds[1] = ILLEGAL_TRIGGER_ID;
02856   tabPtr.p->triggerIds[2] = ILLEGAL_TRIGGER_ID;
02857   tabPtr.p->triggerAllocated[0] = false;
02858   tabPtr.p->triggerAllocated[1] = false;
02859   tabPtr.p->triggerAllocated[2] = false;
02860 
02861   if(tabPtr.p->attributes.seize(tabPtr.p->noOfAttributes) == false) {
02862     jam();
02863     ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
02864     tabPtr.i = RNIL;
02865     return tabPtr;
02866   }//if
02867   
02868   const Uint32 count = tabPtr.p->noOfAttributes;
02869   for(Uint32 i = 0; i<count; i++) {
02870     jam();
02871     DictTabInfo::Attribute tmp; tmp.init();
02872     stat = SimpleProperties::unpack(it, &tmp, 
02873                                     DictTabInfo::AttributeMapping, 
02874                                     DictTabInfo::AttributeMappingSize,
02875                                     true, true);
02876     
02877     ndbrequire(stat == SimpleProperties::Break);
02878 
02879     const Uint32 arr = tmp.AttributeArraySize;
02880     const Uint32 sz = 1 << tmp.AttributeSize;
02881     const Uint32 sz32 = (sz * arr + 31) >> 5;
02882 
02883     AttributePtr attrPtr;
02884     tabPtr.p->attributes.getPtr(attrPtr, tmp.AttributeId);
02885     
02886     attrPtr.p->data.nullable = tmp.AttributeNullableFlag;
02887     attrPtr.p->data.fixed = (tmp.AttributeArraySize != 0);
02888     attrPtr.p->data.sz32 = sz32;
02889 
02896     if(attrPtr.p->data.fixed == true && attrPtr.p->data.nullable == false) {
02897       jam();
02898       attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
02899       tabPtr.p->sz_FixedAttributes += sz32;
02900     }//if
02901     
02902     if(attrPtr.p->data.fixed == true && attrPtr.p->data.nullable == true) {
02903       jam();
02904       attrPtr.p->data.offset = 0;
02905       
02906       attrPtr.p->data.offsetNull = tabPtr.p->noOfNull;
02907       tabPtr.p->noOfNull++;
02908       tabPtr.p->noOfVariable++;
02909     }//if
02910     
02911     if(attrPtr.p->data.fixed == false) {
02912       jam();
02913       tabPtr.p->noOfVariable++;
02914       ndbrequire(0);
02915     }//if
02916     
02917     it.next(); // Move Past EndOfAttribute
02918   }//for
02919   return tabPtr;
02920 }
02921 
02922 void
02923 Backup::execDI_FCOUNTCONF(Signal* signal)
02924 {
02925   jamEntry();
02926   
02927   const Uint32 userPtr = signal->theData[0];
02928   const Uint32 fragCount = signal->theData[1];
02929   const Uint32 tableId = signal->theData[2];
02930   const Uint32 senderData = signal->theData[3];
02931 
02932   ndbrequire(userPtr == RNIL && signal->length() == 5);
02933   
02934   BackupRecordPtr ptr;
02935   c_backupPool.getPtr(ptr, senderData);
02936 
02937   TablePtr tabPtr;
02938   ndbrequire(findTable(ptr, tabPtr, tableId));
02939   
02940   ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
02941   tabPtr.p->frag_mask = calculate_frag_mask(fragCount);
02942   for(Uint32 i = 0; i<fragCount; i++) {
02943     jam();
02944     FragmentPtr fragPtr;
02945     tabPtr.p->fragments.getPtr(fragPtr, i);
02946     fragPtr.p->scanned = 0;
02947     fragPtr.p->scanning = 0;
02948     fragPtr.p->tableId = tableId;
02949     fragPtr.p->node = RNIL;
02950   }//for
02951   
02955   if(ptr.p->tables.next(tabPtr)) {
02956     jam();
02957     signal->theData[0] = RNIL;
02958     signal->theData[1] = tabPtr.p->tableId;
02959     signal->theData[2] = ptr.i;
02960     sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal, 3, JBB);    
02961     return;
02962   }//if
02963   
02964   ptr.p->tables.first(tabPtr);
02965   getFragmentInfo(signal, ptr, tabPtr, 0);
02966 }
02967 
02968 void
02969 Backup::getFragmentInfo(Signal* signal, 
02970                         BackupRecordPtr ptr, TablePtr tabPtr, Uint32 fragNo)
02971 {
02972   jam();
02973   
02974   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
02975     jam();
02976     const Uint32 fragCount = tabPtr.p->fragments.getSize();
02977     for(; fragNo < fragCount; fragNo ++) {
02978       jam();
02979       FragmentPtr fragPtr;
02980       tabPtr.p->fragments.getPtr(fragPtr, fragNo);
02981       
02982       if(fragPtr.p->scanned == 0 && fragPtr.p->scanning == 0) {
02983         jam();
02984         signal->theData[0] = RNIL;
02985         signal->theData[1] = ptr.i;
02986         signal->theData[2] = tabPtr.p->tableId;
02987         signal->theData[3] = fragNo;
02988         sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
02989         return;
02990       }//if
02991     }//for
02992     fragNo = 0;
02993   }//for
02994   
02995   getFragmentInfoDone(signal, ptr);
02996 }
02997 
02998 void
02999 Backup::execDIGETPRIMCONF(Signal* signal)
03000 {
03001   jamEntry();
03002   
03003   const Uint32 userPtr = signal->theData[0];
03004   const Uint32 senderData = signal->theData[1];
03005   const Uint32 nodeCount = signal->theData[6];
03006   const Uint32 tableId = signal->theData[7];
03007   const Uint32 fragNo = signal->theData[8];
03008 
03009   ndbrequire(userPtr == RNIL && signal->length() == 9);
03010   ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
03011   
03012   BackupRecordPtr ptr;
03013   c_backupPool.getPtr(ptr, senderData);
03014 
03015   TablePtr tabPtr;
03016   ndbrequire(findTable(ptr, tabPtr, tableId));
03017 
03018   FragmentPtr fragPtr;
03019   tabPtr.p->fragments.getPtr(fragPtr, fragNo);
03020 
03021   fragPtr.p->node = signal->theData[2];
03022 
03023   getFragmentInfo(signal, ptr, tabPtr, fragNo + 1);
03024 }
03025 
03026 void
03027 Backup::getFragmentInfoDone(Signal* signal, BackupRecordPtr ptr)
03028 {
03029   ptr.p->m_gsn = GSN_DEFINE_BACKUP_CONF;
03030   ptr.p->slaveState.setState(DEFINED);
03031   DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtr();
03032   conf->backupPtr = ptr.i;
03033   conf->backupId = ptr.p->backupId;
03034   sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_CONF, signal,
03035              DefineBackupConf::SignalLength, JBB);
03036 }
03037 
03038 
03039 /*****************************************************************************
03040  * 
03041  * Slave functionallity: Start backup
03042  *
03043  *****************************************************************************/
03044 void
03045 Backup::execSTART_BACKUP_REQ(Signal* signal)
03046 {
03047   jamEntry();
03048 
03049   CRASH_INSERTION((10015));
03050   
03051   StartBackupReq* req = (StartBackupReq*)signal->getDataPtr();
03052   const Uint32 ptrI = req->backupPtr;
03053   //const Uint32 backupId = req->backupId;
03054   const Uint32 signalNo = req->signalNo;
03055   
03056   BackupRecordPtr ptr;
03057   c_backupPool.getPtr(ptr, ptrI);
03058   
03059   ptr.p->slaveState.setState(STARTED);
03060   ptr.p->m_gsn = GSN_START_BACKUP_REQ;
03061 
03062   for(Uint32 i = 0; i<req->noOfTableTriggers; i++) {
03063     jam();
03064     TablePtr tabPtr;
03065     ndbrequire(findTable(ptr, tabPtr, req->tableTriggers[i].tableId));
03066     for(Uint32 j = 0; j<3; j++) {
03067       jam();
03068       const Uint32 triggerId = req->tableTriggers[i].triggerIds[j];
03069       tabPtr.p->triggerIds[j] = triggerId;
03070       
03071       TriggerPtr trigPtr;
03072       if(!ptr.p->triggers.seizeId(trigPtr, triggerId)) {
03073         jam();
03074         ptr.p->m_gsn = GSN_START_BACKUP_REF;
03075         StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
03076         ref->backupPtr = ptr.i;
03077         ref->backupId = ptr.p->backupId;
03078         ref->signalNo = signalNo;
03079         ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
03080         ref->nodeId = getOwnNodeId();
03081         sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
03082                    StartBackupRef::SignalLength, JBB);
03083         return;
03084       }//if
03085 
03086       tabPtr.p->triggerAllocated[j] = true;
03087       trigPtr.p->backupPtr = ptr.i;
03088       trigPtr.p->tableId = tabPtr.p->tableId;
03089       trigPtr.p->tab_ptr_i = tabPtr.i;
03090       trigPtr.p->logEntry = 0;
03091       trigPtr.p->event = j;
03092       trigPtr.p->maxRecordSize = 2048;
03093       trigPtr.p->operation = 
03094         &ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
03095       trigPtr.p->operation->noOfBytes = 0;
03096       trigPtr.p->operation->noOfRecords = 0;
03097       trigPtr.p->errorCode = 0;
03098     }//for
03099   }//for
03100   
03104   BackupFilePtr filePtr;
03105   for(ptr.p->files.first(filePtr); 
03106       filePtr.i!=RNIL; 
03107       ptr.p->files.next(filePtr)){
03108     jam();
03109     if(filePtr.p->fileRunning == 0) {
03110       jam();
03111       filePtr.p->fileRunning = 1;
03112       signal->theData[0] = BackupContinueB::START_FILE_THREAD;
03113       signal->theData[1] = filePtr.i;
03114       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
03115     }//if
03116   }//for
03117   
03118   ptr.p->m_gsn = GSN_START_BACKUP_CONF;
03119   StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend();
03120   conf->backupPtr = ptr.i;
03121   conf->backupId = ptr.p->backupId;
03122   conf->signalNo = signalNo;
03123   sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal,
03124              StartBackupConf::SignalLength, JBB);
03125 }
03126 
03127 /*****************************************************************************
03128  * 
03129  * Slave functionallity: Backup fragment
03130  *
03131  *****************************************************************************/
03132 void
03133 Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
03134 {
03135   jamEntry();
03136   BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtr();
03137 
03138   CRASH_INSERTION((10016));
03139 
03140   const Uint32 ptrI = req->backupPtr;
03141   //const Uint32 backupId = req->backupId;
03142   const Uint32 tableId = req->tableId;
03143   const Uint32 fragNo = req->fragmentNo;
03144   const Uint32 count = req->count;
03145   
03149   BackupRecordPtr ptr;
03150   c_backupPool.getPtr(ptr, ptrI);
03151 
03152   ptr.p->slaveState.setState(SCANNING);
03153   ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REQ;
03154 
03158   BackupFilePtr filePtr;
03159   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
03160   
03161   ndbrequire(filePtr.p->backupPtr == ptrI);
03162   ndbrequire(filePtr.p->fileOpened == 1);
03163   ndbrequire(filePtr.p->fileRunning == 1);
03164   ndbrequire(filePtr.p->scanRunning == 0);
03165   ndbrequire(filePtr.p->fileClosing == 0);
03166   
03170   TablePtr tabPtr;
03171   ndbrequire(findTable(ptr, tabPtr, tableId));
03172 
03176   FragmentPtr fragPtr;
03177   tabPtr.p->fragments.getPtr(fragPtr, fragNo);
03178 
03179   ndbrequire(fragPtr.p->scanned == 0);
03180   ndbrequire(fragPtr.p->scanning == 0 || 
03181              refToNode(ptr.p->masterRef) == getOwnNodeId());
03182   
03186   if(filePtr.p->tableId != tableId) {
03187     jam();
03188     filePtr.p->operation.init(tabPtr);
03189     filePtr.p->tableId = tableId;
03190   }//if
03191   
03195   if(!filePtr.p->operation.newFragment(tableId, fragNo)) {
03196     jam();
03197     req->count = count + 1;
03198     sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
03199                         signal->length());
03200     ptr.p->slaveState.setState(STARTED);
03201     return;
03202   }//if
03203   
03207   fragPtr.p->scanning = 1;
03208   filePtr.p->fragmentNo = fragNo;
03209 
03213   {
03214     filePtr.p->scanRunning = 1;
03215     
03216     Table & table = * tabPtr.p;
03217     ScanFragReq * req = (ScanFragReq *)signal->getDataPtrSend();
03218     const Uint32 parallelism = 16;
03219     const Uint32 attrLen = 5 + table.noOfAttributes;
03220 
03221     req->senderData = filePtr.i;
03222     req->resultRef = reference();
03223     req->schemaVersion = table.schemaVersion;
03224     req->fragmentNoKeyLen = fragNo;
03225     req->requestInfo = 0;
03226     req->savePointId = 0;
03227     req->tableId = table.tableId;
03228     ScanFragReq::setLockMode(req->requestInfo, 0);
03229     ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
03230     ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
03231     ScanFragReq::setAttrLen(req->requestInfo,attrLen); 
03232     req->transId1 = 0;
03233     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
03234     req->clientOpPtr= filePtr.i;
03235     req->batch_size_rows= parallelism;
03236     req->batch_size_bytes= 0;
03237     sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal,
03238                ScanFragReq::SignalLength, JBB);
03239     
03240     signal->theData[0] = filePtr.i;
03241     signal->theData[1] = 0;
03242     signal->theData[2] = (BACKUP << 20) + (getOwnNodeId() << 8);
03243     
03244     // Return all
03245     signal->theData[3] = table.noOfAttributes;
03246     signal->theData[4] = 0;
03247     signal->theData[5] = 0;
03248     signal->theData[6] = 0;
03249     signal->theData[7] = 0;
03250     
03251     Uint32 dataPos = 8;
03252     Uint32 i;
03253     for(i = 0; i<table.noOfAttributes; i++) {
03254       jam();
03255       AttributePtr attr;
03256       table.attributes.getPtr(attr, i);
03257       
03258       AttributeHeader::init(&signal->theData[dataPos], i, 0);
03259       dataPos++;
03260       if(dataPos == 25) {
03261         jam();
03262         sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, 25, JBB);
03263         dataPos = 3;
03264       }//if
03265     }//for
03266     if(dataPos != 3) {
03267       jam();
03268       sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, dataPos, JBB);
03269     }//if
03270   }
03271 }
03272 
03273 void
03274 Backup::execSCAN_HBREP(Signal* signal)
03275 {
03276   jamEntry();
03277 }
03278 
03279 void
03280 Backup::execTRANSID_AI(Signal* signal)
03281 {
03282   jamEntry();
03283 
03284   const Uint32 filePtrI = signal->theData[0];
03285   //const Uint32 transId1 = signal->theData[1];
03286   //const Uint32 transId2 = signal->theData[2];
03287   const Uint32 dataLen  = signal->length() - 3;
03288   
03289   BackupFilePtr filePtr;
03290   c_backupFilePool.getPtr(filePtr, filePtrI);
03291 
03292   OperationRecord & op = filePtr.p->operation;
03293   
03294   TablePtr tabPtr;
03295   c_tablePool.getPtr(tabPtr, op.tablePtr);
03296   
03297   Table & table = * tabPtr.p;
03298   
03302   op.attrSzTotal += dataLen;
03303 
03304   Uint32 srcSz = dataLen;
03305   const Uint32 * src = &signal->theData[3];
03306 
03307   Uint32 * dst = op.dst;
03308   Uint32 dstSz = op.attrSzLeft;
03309   
03310   while(srcSz > 0) {
03311     jam();
03312 
03313     if(dstSz == 0) {
03314       jam();
03315 
03319       const AttributeHeader attrHead(* src);
03320       const Uint32 attrId = attrHead.getAttributeId();
03321       const bool null = attrHead.isNULL();
03322       const Attribute::Data attr = table.attributes.getPtr(attrId)->data;
03323       
03324       srcSz -= attrHead.getHeaderSize();
03325       src   += attrHead.getHeaderSize();
03326       
03327       if(null) {
03328         jam();
03329         ndbrequire(attr.nullable);
03330         op.nullAttribute(attr.offsetNull);
03331         dstSz = 0;
03332         continue;
03333       }//if
03334       
03335       dstSz = attrHead.getDataSize();
03336       ndbrequire(dstSz == attr.sz32);
03337       if(attr.fixed && ! attr.nullable) {
03338         jam();
03339         dst = op.newAttrib(attr.offset, dstSz);
03340       } else if (attr.fixed && attr.nullable) {
03341         jam();
03342         dst = op.newNullable(attrId, dstSz);
03343       } else {
03344         ndbrequire(false);
03345         //dst = op.newVariable(attrId, attrSize);
03346       }//if
03347     }//if
03348     
03349     const Uint32 szCopy = (dstSz > srcSz) ? srcSz : dstSz;
03350     memcpy(dst, src, (szCopy << 2));
03351 
03352     srcSz -= szCopy;
03353     dstSz -= szCopy;
03354     src   += szCopy;
03355     dst   += szCopy;
03356   }//while
03357   op.dst        = dst;
03358   op.attrSzLeft = dstSz;
03359   
03360   if(op.finished()){
03361     jam();
03362     op.newRecord(op.dst);
03363   }
03364 }
03365 
03366 void 
03367 Backup::OperationRecord::init(const TablePtr & ptr)
03368 {
03369   
03370   tablePtr = ptr.i;
03371   noOfAttributes = ptr.p->noOfAttributes;
03372   
03373   sz_Bitmask = (ptr.p->noOfNull + 31) >> 5;
03374   sz_FixedAttribs = ptr.p->sz_FixedAttributes;
03375 
03376   if(ptr.p->noOfVariable == 0) {
03377     jam();
03378     maxRecordSize = 1 + sz_Bitmask + sz_FixedAttribs;
03379   } else {
03380     jam();
03381     maxRecordSize = 
03382       1 + sz_Bitmask + 2048 /* Max tuple size */ + 2 * ptr.p->noOfVariable;
03383   }//if
03384 }
03385 
03386 bool
03387 Backup::OperationRecord::newFragment(Uint32 tableId, Uint32 fragNo)
03388 {
03389   Uint32 * tmp;
03390   const Uint32 headSz = (sizeof(BackupFormat::DataFile::FragmentHeader) >> 2);
03391   const Uint32 sz = headSz + 16 * maxRecordSize;
03392   
03393   ndbrequire(sz < dataBuffer.getMaxWrite());
03394   if(dataBuffer.getWritePtr(&tmp, sz)) {
03395     jam();
03396     BackupFormat::DataFile::FragmentHeader * head = 
03397       (BackupFormat::DataFile::FragmentHeader*)tmp;
03398 
03399     head->SectionType   = htonl(BackupFormat::FRAGMENT_HEADER);
03400     head->SectionLength = htonl(headSz);
03401     head->TableId       = htonl(tableId);
03402     head->FragmentNo    = htonl(fragNo);
03403     head->ChecksumType  = htonl(0);
03404 
03405     opNoDone = opNoConf = opLen = 0;
03406     newRecord(tmp + headSz);
03407     scanStart = tmp;
03408     scanStop  = (tmp + headSz);
03409     
03410     noOfRecords = 0;
03411     noOfBytes = 0;
03412     return true;
03413   }//if
03414   return false;
03415 }
03416 
03417 bool
03418 Backup::OperationRecord::fragComplete(Uint32 tableId, Uint32 fragNo)
03419 {
03420   Uint32 * tmp;
03421   const Uint32 footSz = sizeof(BackupFormat::DataFile::FragmentFooter) >> 2;
03422 
03423   if(dataBuffer.getWritePtr(&tmp, footSz + 1)) {
03424     jam();
03425     * tmp = 0; // Finish record stream
03426     tmp++;
03427     BackupFormat::DataFile::FragmentFooter * foot = 
03428       (BackupFormat::DataFile::FragmentFooter*)tmp;
03429     foot->SectionType   = htonl(BackupFormat::FRAGMENT_FOOTER);
03430     foot->SectionLength = htonl(footSz);
03431     foot->TableId       = htonl(tableId);
03432     foot->FragmentNo    = htonl(fragNo);
03433     foot->NoOfRecords   = htonl(noOfRecords);
03434     foot->Checksum      = htonl(0);
03435     dataBuffer.updateWritePtr(footSz + 1);
03436     return true;
03437   }//if
03438   return false;
03439 }
03440 
03441 bool
03442 Backup::OperationRecord::newScan()
03443 {
03444   Uint32 * tmp;
03445   ndbrequire(16 * maxRecordSize < dataBuffer.getMaxWrite());
03446   if(dataBuffer.getWritePtr(&tmp, 16 * maxRecordSize)) {
03447     jam();
03448     opNoDone = opNoConf = opLen = 0;
03449     newRecord(tmp);
03450     scanStart = tmp;
03451     scanStop = tmp;
03452     return true;
03453   }//if
03454   return false;
03455 }
03456 
03457 bool
03458 Backup::OperationRecord::closeScan()
03459 {
03460   opNoDone = opNoConf = opLen = 0;
03461   return true;
03462 }
03463 
03464 bool 
03465 Backup::OperationRecord::scanConf(Uint32 noOfOps, Uint32 total_len)
03466 {
03467   const Uint32 done = opNoDone-opNoConf;
03468   
03469   ndbrequire(noOfOps == done);
03470   ndbrequire(opLen == total_len);
03471   opNoConf = opNoDone;
03472   
03473   const Uint32 len = (scanStop - scanStart);
03474   ndbrequire(len < dataBuffer.getMaxWrite());
03475   dataBuffer.updateWritePtr(len);
03476   noOfBytes += (len << 2);
03477   return true;
03478 }
03479 
03480 void
03481 Backup::execSCAN_FRAGREF(Signal* signal)
03482 {
03483   jamEntry();
03484 
03485   ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr();
03486   
03487   const Uint32 filePtrI = ref->senderData;
03488   BackupFilePtr filePtr;
03489   c_backupFilePool.getPtr(filePtr, filePtrI);
03490   
03491   filePtr.p->errorCode = ref->errorCode;
03492   filePtr.p->scanRunning = 0;
03493   
03494   backupFragmentRef(signal, filePtr);
03495 }
03496 
03497 void
03498 Backup::execSCAN_FRAGCONF(Signal* signal)
03499 {
03500   jamEntry();
03501 
03502   CRASH_INSERTION((10017));
03503 
03504   ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr();
03505   
03506   const Uint32 filePtrI = conf->senderData;
03507   BackupFilePtr filePtr;
03508   c_backupFilePool.getPtr(filePtr, filePtrI);
03509 
03510   OperationRecord & op = filePtr.p->operation;
03511   
03512   op.scanConf(conf->completedOps, conf->total_len);
03513   const Uint32 completed = conf->fragmentCompleted;
03514   if(completed != 2) {
03515     jam();
03516     
03517     checkScan(signal, filePtr);
03518     return;
03519   }//if
03520 
03521   fragmentCompleted(signal, filePtr);
03522 }
03523 
03524 void
03525 Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
03526 {
03527   jam();
03528 
03529   if(filePtr.p->errorCode != 0)
03530   {
03531     jam();    
03532     filePtr.p->scanRunning = 0;
03533     backupFragmentRef(signal, filePtr); // Scan completed
03534     return;
03535   }//if
03536     
03537   OperationRecord & op = filePtr.p->operation;
03538   if(!op.fragComplete(filePtr.p->tableId, filePtr.p->fragmentNo)) {
03539     jam();
03540     signal->theData[0] = BackupContinueB::BUFFER_FULL_FRAG_COMPLETE;
03541     signal->theData[1] = filePtr.i;
03542     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
03543     return;
03544   }//if
03545   
03546   filePtr.p->scanRunning = 0;
03547   
03548   BackupRecordPtr ptr;
03549   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
03550 
03551   BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
03552   conf->backupId = ptr.p->backupId;
03553   conf->backupPtr = ptr.i;
03554   conf->tableId = filePtr.p->tableId;
03555   conf->fragmentNo = filePtr.p->fragmentNo;
03556   conf->noOfRecords = op.noOfRecords;
03557   conf->noOfBytes = op.noOfBytes;
03558   sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
03559              BackupFragmentConf::SignalLength, JBB);
03560   
03561   ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_CONF;
03562   ptr.p->slaveState.setState(STARTED);
03563   return;
03564 }
03565 
03566 void
03567 Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr)
03568 {
03569   BackupRecordPtr ptr;
03570   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
03571 
03572   ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF;
03573   
03574   BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtrSend();
03575   ref->backupId = ptr.p->backupId;
03576   ref->backupPtr = ptr.i;
03577   ref->nodeId = getOwnNodeId();
03578   ref->errorCode = ptr.p->errorCode;
03579   sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal,
03580              BackupFragmentRef::SignalLength, JBB);
03581 }
03582  
03583 void
03584 Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
03585 {  
03586   OperationRecord & op = filePtr.p->operation;
03587 
03588   if(filePtr.p->errorCode != 0)
03589   {
03590     jam();
03591 
03595     op.closeScan();
03596     ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
03597     req->senderData = filePtr.i;
03598     req->closeFlag = 1;
03599     req->transId1 = 0;
03600     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
03601     sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, 
03602                ScanFragNextReq::SignalLength, JBB);
03603     return;
03604   }//if
03605   
03606   if(op.newScan()) {
03607     jam();
03608     
03609     ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
03610     req->senderData = filePtr.i;
03611     req->closeFlag = 0;
03612     req->transId1 = 0;
03613     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
03614     req->batch_size_rows= 16;
03615     req->batch_size_bytes= 0;
03616     if(ERROR_INSERTED(10032))
03617       sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, 
03618                           100, ScanFragNextReq::SignalLength);
03619     else if(ERROR_INSERTED(10033))
03620     {
03621       SET_ERROR_INSERT_VALUE(10032);
03622       sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, 
03623                           10000, ScanFragNextReq::SignalLength);
03624       
03625       BackupRecordPtr ptr;
03626       c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
03627       AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
03628       ord->backupId = ptr.p->backupId;
03629       ord->backupPtr = ptr.i;
03630       ord->requestType = AbortBackupOrd::FileOrScanError;
03631       ord->senderData= ptr.i;
03632       sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, 
03633                  AbortBackupOrd::SignalLength, JBB);
03634     }
03635     else
03636       sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, 
03637                  ScanFragNextReq::SignalLength, JBB);
03638     return;
03639   }//if
03640   
03641   signal->theData[0] = BackupContinueB::BUFFER_FULL_SCAN;
03642   signal->theData[1] = filePtr.i;
03643   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
03644 }
03645 
03646 void
03647 Backup::execFSAPPENDREF(Signal* signal)
03648 {
03649   jamEntry();
03650   
03651   FsRef * ref = (FsRef *)signal->getDataPtr();
03652 
03653   const Uint32 filePtrI = ref->userPointer;
03654   const Uint32 errCode = ref->errorCode;
03655   
03656   BackupFilePtr filePtr;
03657   c_backupFilePool.getPtr(filePtr, filePtrI);
03658 
03659   filePtr.p->fileRunning = 0;  
03660   filePtr.p->errorCode = errCode;
03661 
03662   checkFile(signal, filePtr);
03663 }
03664 
03665 void
03666 Backup::execFSAPPENDCONF(Signal* signal)
03667 {
03668   jamEntry();
03669   
03670   CRASH_INSERTION((10018));
03671 
03672   //FsConf * conf = (FsConf*)signal->getDataPtr();
03673   const Uint32 filePtrI = signal->theData[0]; //conf->userPointer;
03674   const Uint32 bytes = signal->theData[1]; //conf->bytes;
03675   
03676   BackupFilePtr filePtr;
03677   c_backupFilePool.getPtr(filePtr, filePtrI);
03678   
03679   OperationRecord & op = filePtr.p->operation;
03680   
03681   op.dataBuffer.updateReadPtr(bytes >> 2);
03682 
03683   checkFile(signal, filePtr);
03684 }
03685 
03686 void
03687 Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
03688 {
03689 
03690 #ifdef DEBUG_ABORT
03691   //  ndbout_c("---- check file filePtr.i = %u", filePtr.i);
03692 #endif
03693 
03694   OperationRecord & op = filePtr.p->operation;
03695   
03696   Uint32 * tmp, sz; bool eof;
03697   if(op.dataBuffer.getReadPtr(&tmp, &sz, &eof)) 
03698   {
03699     jam();
03700     
03701     jam();
03702     FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend();
03703     req->filePointer   = filePtr.p->filePointer;
03704     req->userPointer   = filePtr.i;
03705     req->userReference = reference();
03706     req->varIndex      = 0;
03707     req->offset        = tmp - c_startOfPages;
03708     req->size          = sz;
03709     
03710     sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, 
03711                FsAppendReq::SignalLength, JBA);
03712     return;
03713   }
03714   
03715   if(!eof) {
03716     jam();
03717     signal->theData[0] = BackupContinueB::BUFFER_UNDERFLOW;
03718     signal->theData[1] = filePtr.i;
03719     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
03720     return;
03721   }//if
03722   
03723   if(sz > 0) {
03724     jam();
03725     FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend();
03726     req->filePointer   = filePtr.p->filePointer;
03727     req->userPointer   = filePtr.i;
03728     req->userReference = reference();
03729     req->varIndex      = 0;
03730     req->offset        = tmp - c_startOfPages;
03731     req->size          = sz; // Avrunda uppot
03732     
03733     sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, 
03734                FsAppendReq::SignalLength, JBA);
03735     return;
03736   }//if
03737   
03738   filePtr.p->fileRunning = 0;
03739   filePtr.p->fileClosing = 1;
03740   
03741   FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend();
03742   req->filePointer = filePtr.p->filePointer;
03743   req->userPointer = filePtr.i;
03744   req->userReference = reference();
03745   req->fileFlag = 0;
03746 #ifdef DEBUG_ABORT
03747   ndbout_c("***** a FSCLOSEREQ filePtr.i = %u", filePtr.i);
03748 #endif
03749   sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
03750 }
03751 
03752 
03753 /****************************************************************************
03754  * 
03755  * Slave functionallity: Perform logging
03756  *
03757  ****************************************************************************/
03758 Uint32
03759 Backup::calculate_frag_mask(Uint32 count)
03760 {
03761   Uint32 mask = 1;
03762   while (mask < count) mask <<= 1;
03763   mask -= 1;
03764   return mask;
03765 }
03766 
03767 void
03768 Backup::execBACKUP_TRIG_REQ(Signal* signal)
03769 {
03770   /*
03771   TUP asks if this trigger is to be fired on this node.
03772   */
03773   TriggerPtr trigPtr;
03774   TablePtr tabPtr;
03775   FragmentPtr fragPtr;
03776   Uint32 trigger_id = signal->theData[0];
03777   Uint32 frag_id = signal->theData[1];
03778   Uint32 result;
03779 
03780   jamEntry();
03781   c_triggerPool.getPtr(trigPtr, trigger_id);
03782   c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
03783   frag_id = frag_id & tabPtr.p->frag_mask;
03784   /*
03785   At the moment the fragment identity known by TUP is the
03786   actual fragment id but with possibly an extra bit set.
03787   This is due to that ACC splits the fragment. Thus fragment id 5 can
03788   here be either 5 or 13. Thus masking with 2 ** n - 1 where number of
03789   fragments <= 2 ** n will always provide a correct fragment id.
03790   */
03791   tabPtr.p->fragments.getPtr(fragPtr, frag_id);
03792   if (fragPtr.p->node != getOwnNodeId()) {
03793     jam();
03794     result = ZFALSE;
03795   } else {
03796     jam();
03797     result = ZTRUE;
03798   }//if
03799   signal->theData[0] = result;
03800 }
03801 
03802 void
03803 Backup::execTRIG_ATTRINFO(Signal* signal) {
03804   jamEntry();
03805 
03806   CRASH_INSERTION((10019));
03807 
03808   TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr();
03809 
03810   TriggerPtr trigPtr;
03811   c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
03812   ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
03813   
03814   if(trigPtr.p->errorCode != 0) {
03815     jam();
03816     return;
03817   }//if
03818   
03819   if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
03820     jam();
03824     return;
03825   }//if
03826 
03827   BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
03828   if(logEntry == 0) 
03829   {
03830     jam();
03831     Uint32 * dst;
03832     FsBuffer & buf = trigPtr.p->operation->dataBuffer;
03833     ndbrequire(trigPtr.p->maxRecordSize <= buf.getMaxWrite());
03834 
03835     if(ERROR_INSERTED(10030) ||
03836        !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize)) 
03837     {
03838       jam();
03839       BackupRecordPtr ptr;
03840       c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
03841       trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull;
03842       AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
03843       ord->backupId = ptr.p->backupId;
03844       ord->backupPtr = ptr.i;
03845       ord->requestType = AbortBackupOrd::LogBufferFull;
03846       ord->senderData= ptr.i;
03847       sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal, 
03848                  AbortBackupOrd::SignalLength, JBB);
03849       return;
03850     }//if
03851         
03852     logEntry = (BackupFormat::LogFile::LogEntry *)dst;
03853     trigPtr.p->logEntry = logEntry;
03854     logEntry->Length       = 0;
03855     logEntry->TableId      = htonl(trigPtr.p->tableId);
03856     logEntry->TriggerEvent = htonl(trigPtr.p->event);
03857   } else {
03858     ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId));
03859     ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event));
03860   }//if
03861   
03862   const Uint32 pos = logEntry->Length; 
03863   const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
03864   memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2);
03865 
03866   logEntry->Length = pos + dataLen;
03867 }
03868 
03869 void
03870 Backup::execFIRE_TRIG_ORD(Signal* signal)
03871 {
03872   jamEntry();
03873   FireTrigOrd* trg = (FireTrigOrd*)signal->getDataPtr();
03874 
03875   const Uint32 gci = trg->getGCI();
03876   const Uint32 trI = trg->getTriggerId();
03877 
03878   TriggerPtr trigPtr;
03879   c_triggerPool.getPtr(trigPtr, trI);
03880   
03881   ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
03882 
03883   if(trigPtr.p->errorCode != 0) {
03884     jam();
03885     return;
03886   }//if
03887 
03888   ndbrequire(trigPtr.p->logEntry != 0);
03889   Uint32 len = trigPtr.p->logEntry->Length;
03890 
03891   BackupRecordPtr ptr;
03892   c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
03893   if(gci != ptr.p->currGCP) 
03894   {
03895     jam();
03896     
03897     trigPtr.p->logEntry->TriggerEvent = htonl(trigPtr.p->event | 0x10000);
03898     trigPtr.p->logEntry->Data[len] = htonl(gci);
03899     len ++;
03900     ptr.p->currGCP = gci;
03901   }//if
03902   
03903   len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
03904   trigPtr.p->logEntry->Length = htonl(len);
03905 
03906   ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
03907   trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
03908   trigPtr.p->logEntry = 0;
03909   
03910   trigPtr.p->operation->noOfBytes += (len + 1) << 2;
03911   trigPtr.p->operation->noOfRecords += 1;
03912 }
03913 
03914 void
03915 Backup::sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr, 
03916                            Uint32 requestType)
03917 {
03918   jam();
03919   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
03920   ord->backupId = ptr.p->backupId;
03921   ord->backupPtr = ptr.i;
03922   ord->requestType = requestType;
03923   ord->senderData= ptr.i;
03924   NodePtr node;
03925   for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
03926     jam();
03927     const Uint32 nodeId = node.p->nodeId;
03928     if(node.p->alive && ptr.p->nodes.get(nodeId)) {
03929       jam();
03930       sendSignal(numberToRef(BACKUP, nodeId), GSN_ABORT_BACKUP_ORD, signal, 
03931                  AbortBackupOrd::SignalLength, JBB);
03932     }//if
03933   }//for
03934 }
03935 
03936 /*****************************************************************************
03937  * 
03938  * Slave functionallity: Stop backup
03939  *
03940  *****************************************************************************/
03941 void
03942 Backup::execSTOP_BACKUP_REQ(Signal* signal)
03943 {
03944   jamEntry();
03945   StopBackupReq * req = (StopBackupReq*)signal->getDataPtr();
03946   
03947   CRASH_INSERTION((10020));
03948 
03949   const Uint32 ptrI = req->backupPtr;
03950   //const Uint32 backupId = req->backupId;
03951   const Uint32 startGCP = req->startGCP;
03952   const Uint32 stopGCP = req->stopGCP;
03953 
03957   ndbrequire(stopGCP > startGCP);
03958   
03962   BackupRecordPtr ptr;
03963   c_backupPool.getPtr(ptr, ptrI);
03964 
03965   ptr.p->slaveState.setState(STOPPING);
03966   ptr.p->m_gsn = GSN_STOP_BACKUP_REQ;
03967 
03971   {
03972     BackupFilePtr filePtr;
03973     ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
03974     Uint32 * dst;
03975     ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
03976     * dst = 0;
03977     filePtr.p->operation.dataBuffer.updateWritePtr(1);
03978   }
03979 
03980   {
03981     BackupFilePtr filePtr;
03982     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
03983     
03984     const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
03985     
03986     Uint32 * dst;
03987     ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
03988     
03989     BackupFormat::CtlFile::GCPEntry * gcp = 
03990       (BackupFormat::CtlFile::GCPEntry*)dst;
03991     
03992     gcp->SectionType   = htonl(BackupFormat::GCP_ENTRY);
03993     gcp->SectionLength = htonl(gcpSz);
03994     gcp->StartGCP      = htonl(startGCP);
03995     gcp->StopGCP       = htonl(stopGCP - 1);
03996     filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
03997   }
03998   
03999   closeFiles(signal, ptr);
04000 }
04001 
04002 void
04003 Backup::closeFiles(Signal* sig, BackupRecordPtr ptr)
04004 {
04008   BackupFilePtr filePtr;
04009   int openCount = 0;
04010   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL; ptr.p->files.next(filePtr))
04011   {
04012     if(filePtr.p->fileOpened == 0) {
04013       jam();
04014       continue;
04015     }
04016     
04017     jam();
04018     openCount++;
04019     
04020     if(filePtr.p->fileClosing == 1){
04021       jam();
04022       continue;
04023     }//if
04024     
04025     filePtr.p->fileClosing = 1;
04026     
04027     if(filePtr.p->fileRunning == 1){
04028       jam();
04029 #ifdef DEBUG_ABORT
04030       ndbout_c("Close files fileRunning == 1, filePtr.i=%u", filePtr.i);
04031 #endif
04032       filePtr.p->operation.dataBuffer.eof();
04033     } else {
04034       jam();
04035       
04036       FsCloseReq * req = (FsCloseReq *)sig->getDataPtrSend();
04037       req->filePointer = filePtr.p->filePointer;
04038       req->userPointer = filePtr.i;
04039       req->userReference = reference();
04040       req->fileFlag = 0;
04041 #ifdef DEBUG_ABORT
04042       ndbout_c("***** b FSCLOSEREQ filePtr.i = %u", filePtr.i);
04043 #endif
04044       sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, sig, 
04045                  FsCloseReq::SignalLength, JBA);
04046     }//if
04047   }//for
04048   
04049   if(openCount == 0){
04050     jam();
04051     closeFilesDone(sig, ptr);
04052   }//if
04053 }
04054 
04055 void
04056 Backup::execFSCLOSEREF(Signal* signal)
04057 {
04058   jamEntry();
04059   
04060   FsRef * ref = (FsRef*)signal->getDataPtr();
04061   const Uint32 filePtrI = ref->userPointer;
04062   
04063   BackupFilePtr filePtr;
04064   c_backupFilePool.getPtr(filePtr, filePtrI);
04065 
04066   BackupRecordPtr ptr;
04067   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
04068   
04069   filePtr.p->fileOpened = 1;
04070   FsConf * conf = (FsConf*)signal->getDataPtr();
04071   conf->userPointer = filePtrI;
04072   
04073   execFSCLOSECONF(signal);
04074 }
04075 
04076 void
04077 Backup::execFSCLOSECONF(Signal* signal)
04078 {
04079   jamEntry();
04080 
04081   FsConf * conf = (FsConf*)signal->getDataPtr();
04082   const Uint32 filePtrI = conf->userPointer;
04083   
04084   BackupFilePtr filePtr;
04085   c_backupFilePool.getPtr(filePtr, filePtrI);
04086 
04087 #ifdef DEBUG_ABORT
04088   ndbout_c("***** FSCLOSECONF filePtrI = %u", filePtrI);
04089 #endif
04090 
04091   ndbrequire(filePtr.p->fileClosing == 1);
04092   ndbrequire(filePtr.p->fileOpened == 1);
04093   ndbrequire(filePtr.p->fileRunning == 0);
04094   ndbrequire(filePtr.p->scanRunning == 0);           
04095   
04096   filePtr.p->fileOpened = 0;
04097   
04098   BackupRecordPtr ptr;
04099   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
04100   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr)) 
04101   {
04102     jam();
04103     if(filePtr.p->fileOpened == 1) {
04104       jam();
04105 #ifdef DEBUG_ABORT
04106       ndbout_c("waiting for more FSCLOSECONF's filePtr.i = %u", filePtr.i);
04107 #endif
04108       return; // we will be getting more FSCLOSECONF's
04109     }//if
04110   }//for
04111   closeFilesDone(signal, ptr);
04112 }
04113 
04114 void
04115 Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr)
04116 {
04117   jam();
04118   
04119   jam();
04120   BackupFilePtr filePtr;
04121   ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
04122   
04123   StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend();
04124   conf->backupId = ptr.p->backupId;
04125   conf->backupPtr = ptr.i;
04126   conf->noOfLogBytes = filePtr.p->operation.noOfBytes;
04127   conf->noOfLogRecords = filePtr.p->operation.noOfRecords;
04128   sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal,
04129              StopBackupConf::SignalLength, JBB);
04130   
04131   ptr.p->m_gsn = GSN_STOP_BACKUP_CONF;
04132   ptr.p->slaveState.setState(CLEANING);
04133 }
04134 
04135 /*****************************************************************************
04136  * 
04137  * Slave functionallity: Abort backup
04138  *
04139  *****************************************************************************/
04140 /*****************************************************************************
04141  * 
04142  * Slave functionallity: Abort backup
04143  *
04144  *****************************************************************************/
04145 void
04146 Backup::execABORT_BACKUP_ORD(Signal* signal)
04147 {
04148   jamEntry();
04149   AbortBackupOrd* ord = (AbortBackupOrd*)signal->getDataPtr();
04150 
04151   const Uint32 backupId = ord->backupId;
04152   const AbortBackupOrd::RequestType requestType = 
04153     (AbortBackupOrd::RequestType)ord->requestType;
04154   const Uint32 senderData = ord->senderData;
04155   
04156 #ifdef DEBUG_ABORT
04157   ndbout_c("******** ABORT_BACKUP_ORD ********* nodeId = %u", 
04158            refToNode(signal->getSendersBlockRef()));
04159   ndbout_c("backupId = %u, requestType = %u, senderData = %u, ",
04160            backupId, requestType, senderData);
04161   dumpUsedResources();
04162 #endif
04163 
04164   BackupRecordPtr ptr;
04165   if(requestType == AbortBackupOrd::ClientAbort) {
04166     if (getOwnNodeId() != getMasterNodeId()) {
04167       jam();
04168       // forward to master
04169 #ifdef DEBUG_ABORT
04170       ndbout_c("---- Forward to master nodeId = %u", getMasterNodeId());
04171 #endif
04172       sendSignal(calcBackupBlockRef(getMasterNodeId()), GSN_ABORT_BACKUP_ORD, 
04173                  signal, AbortBackupOrd::SignalLength, JBB);
04174       return;
04175     }
04176     jam();
04177     for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
04178       jam();
04179       if(ptr.p->backupId == backupId && ptr.p->clientData == senderData) {
04180         jam();
04181         break;
04182       }//if
04183     }//for
04184     if(ptr.i == RNIL) {
04185       jam();
04186       return;
04187     }//if
04188   } else {
04189     if (c_backupPool.findId(senderData)) {
04190       jam();
04191       c_backupPool.getPtr(ptr, senderData);
04192     } else { 
04193       jam();
04194 #ifdef DEBUG_ABORT
04195       ndbout_c("Backup: abort request type=%u on id=%u,%u not found",
04196                requestType, backupId, senderData);
04197 #endif
04198       return;
04199     }
04200   }//if
04201   
04202   ptr.p->m_gsn = GSN_ABORT_BACKUP_ORD;
04203   const bool isCoordinator = (ptr.p->masterRef == reference());
04204   
04205   bool ok = false;
04206   switch(requestType){
04207 
04211   case AbortBackupOrd::ClientAbort:
04212     jam();
04213     // fall through
04214   case AbortBackupOrd::LogBufferFull:
04215     jam();
04216     // fall through
04217   case AbortBackupOrd::FileOrScanError:
04218     jam();
04219     ndbrequire(isCoordinator);
04220     ptr.p->setErrorCode(requestType);
04221     if(ptr.p->masterData.gsn == GSN_BACKUP_FRAGMENT_REQ)
04222     {
04226       abort_scan(signal, ptr);
04227     }
04228     return;
04229     
04233   case AbortBackupOrd::AbortScan:
04234     jam();
04235     ptr.p->setErrorCode(requestType);
04236     return;
04237     
04238   case AbortBackupOrd::BackupComplete:
04239     jam();
04240     cleanup(signal, ptr);
04241     return;
04242   case AbortBackupOrd::BackupFailure:
04243   case AbortBackupOrd::BackupFailureDueToNodeFail:
04244   case AbortBackupOrd::OkToClean:
04245   case AbortBackupOrd::IncompatibleVersions:
04246 #ifndef VM_TRACE
04247   default:
04248 #endif
04249     ptr.p->setErrorCode(requestType);
04250     ok= true;
04251   }
04252   ndbrequire(ok);
04253   
04254   Uint32 ref= ptr.p->masterRef;
04255   ptr.p->masterRef = reference();
04256   ptr.p->nodes.clear();
04257   ptr.p->nodes.set(getOwnNodeId());
04258   
04259   if(ref == reference())
04260   {
04261     ptr.p->stopGCP= ptr.p->startGCP + 1;
04262     sendDropTrig(signal, ptr);
04263   }
04264   else
04265   {
04266     ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
04267     ptr.p->masterData.sendCounter.clearWaitingFor();
04268     ptr.p->masterData.sendCounter.setWaitingFor(getOwnNodeId());
04269     closeFiles(signal, ptr);
04270   }
04271 }
04272 
04273 
04274 void
04275 Backup::dumpUsedResources()
04276 {
04277   jam();
04278   BackupRecordPtr ptr;
04279 
04280   for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
04281     ndbout_c("Backup id=%u, slaveState.getState = %u, errorCode=%u",
04282              ptr.p->backupId,
04283              ptr.p->slaveState.getState(),
04284              ptr.p->errorCode);
04285 
04286     TablePtr tabPtr;
04287     for(ptr.p->tables.first(tabPtr);
04288         tabPtr.i != RNIL;
04289         ptr.p->tables.next(tabPtr)) {
04290       jam();
04291       for(Uint32 j = 0; j<3; j++) {
04292         jam();
04293         TriggerPtr trigPtr;
04294         if(tabPtr.p->triggerAllocated[j]) {
04295           jam();
04296           c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
04297           ndbout_c("Allocated[%u] Triggerid = %u, event = %u",
04298                  j,
04299                  tabPtr.p->triggerIds[j],
04300                  trigPtr.p->event);
04301         }//if
04302       }//for
04303     }//for
04304     
04305     BackupFilePtr filePtr;
04306     for(ptr.p->files.first(filePtr);
04307         filePtr.i != RNIL;
04308         ptr.p->files.next(filePtr)) {
04309       jam();
04310       ndbout_c("filePtr.i = %u, filePtr.p->fileOpened=%u fileRunning=%u "
04311                "scanRunning=%u",
04312                filePtr.i,
04313                filePtr.p->fileOpened,
04314                filePtr.p->fileRunning,
04315                filePtr.p->scanRunning);
04316     }//for
04317   }
04318 }
04319 
04320 void
04321 Backup::cleanup(Signal* signal, BackupRecordPtr ptr)
04322 {
04323 
04324   TablePtr tabPtr;
04325   for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;ptr.p->tables.next(tabPtr))
04326   {
04327     jam();
04328     tabPtr.p->attributes.release();
04329     tabPtr.p->fragments.release();
04330     for(Uint32 j = 0; j<3; j++) {
04331       jam();
04332       TriggerPtr trigPtr;
04333       if(tabPtr.p->triggerAllocated[j]) {
04334         jam();
04335         c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
04336         trigPtr.p->event = ILLEGAL_TRIGGER_ID;
04337         tabPtr.p->triggerAllocated[j] = false;
04338       }//if
04339       tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID;
04340     }//for
04341   }//for
04342 
04343   BackupFilePtr filePtr;
04344   for(ptr.p->files.first(filePtr);
04345       filePtr.i != RNIL; 
04346       ptr.p->files.next(filePtr)) {
04347     jam();
04348     ndbrequire(filePtr.p->fileOpened == 0);
04349     ndbrequire(filePtr.p->fileRunning == 0);
04350     ndbrequire(filePtr.p->scanRunning == 0);
04351     filePtr.p->pages.release();
04352   }//for
04353 
04354   ptr.p->files.release();
04355   ptr.p->tables.release();
04356   ptr.p->triggers.release();
04357 
04358   ptr.p->tables.release();
04359   ptr.p->triggers.release();
04360   ptr.p->pages.release();
04361   ptr.p->backupId = ~0;
04362   
04363   if(ptr.p->checkError())
04364     removeBackup(signal, ptr);
04365   else
04366     c_backups.release(ptr);
04367 }
04368 
04369 
04370 void
04371 Backup::removeBackup(Signal* signal, BackupRecordPtr ptr)
04372 {
04373   jam();
04374   
04375   FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
04376   req->userReference = reference();
04377   req->userPointer = ptr.i;
04378   req->directory = 1;
04379   req->ownDirectory = 1;
04380   FsOpenReq::setVersion(req->fileNumber, 2);
04381   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
04382   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
04383   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
04384   sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, 
04385              FsRemoveReq::SignalLength, JBA);
04386 }
04387 
04388 void
04389 Backup::execFSREMOVEREF(Signal* signal)
04390 {
04391   jamEntry();
04392   FsRef * ref = (FsRef*)signal->getDataPtr();
04393   const Uint32 ptrI = ref->userPointer;
04394 
04395   FsConf * conf = (FsConf*)signal->getDataPtr();
04396   conf->userPointer = ptrI;
04397   execFSREMOVECONF(signal);
04398 }
04399 
04400 void
04401 Backup::execFSREMOVECONF(Signal* signal){
04402   jamEntry();
04403 
04404   FsConf * conf = (FsConf*)signal->getDataPtr();
04405   const Uint32 ptrI = conf->userPointer;
04406   
04410   BackupRecordPtr ptr;
04411   c_backupPool.getPtr(ptr, ptrI);
04412   c_backups.release(ptr);
04413 }
04414 

Generated on Wed Jul 20 21:05:14 2005 for MySQL 5.0.9 Beta by  doxygen 1.4.3