1 /* Copyright (c) 2003-2008 MySQL AB
2    Use is subject to license terms
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #include <my_config.h>
18 #include "Backup.hpp"
19 
20 #include <ndb_version.h>
21 
22 #include <NdbTCP.h>
23 #include <Bitmask.hpp>
24 
25 #include <signaldata/NodeFailRep.hpp>
26 #include <signaldata/ReadNodesConf.hpp>
27 
28 #include <signaldata/DihFragCount.hpp>
29 #include <signaldata/ScanFrag.hpp>
30 
31 #include <signaldata/GetTabInfo.hpp>
32 #include <signaldata/DictTabInfo.hpp>
33 #include <signaldata/ListTables.hpp>
34 
35 #include <signaldata/FsOpenReq.hpp>
36 #include <signaldata/FsAppendReq.hpp>
37 #include <signaldata/FsCloseReq.hpp>
38 #include <signaldata/FsConf.hpp>
39 #include <signaldata/FsRef.hpp>
40 #include <signaldata/FsRemoveReq.hpp>
41 
42 #include <signaldata/BackupImpl.hpp>
43 #include <signaldata/BackupSignalData.hpp>
44 #include <signaldata/BackupContinueB.hpp>
45 #include <signaldata/EventReport.hpp>
46 
47 #include <signaldata/UtilSequence.hpp>
48 
49 #include <signaldata/CreateTrig.hpp>
50 #include <signaldata/AlterTrig.hpp>
51 #include <signaldata/DropTrig.hpp>
52 #include <signaldata/FireTrigOrd.hpp>
53 #include <signaldata/TrigAttrInfo.hpp>
54 #include <AttributeHeader.hpp>
55 
56 #include <signaldata/WaitGCP.hpp>
57 #include <signaldata/LCP.hpp>
58 
59 #include <NdbTick.h>
60 
61 static NDB_TICKS startTime;
62 
63 static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
64 
65 #ifdef VM_TRACE
66 #define DEBUG_OUT(x) ndbout << x << endl
67 #else
68 #define DEBUG_OUT(x)
69 #endif
70 
71 //#define DEBUG_ABORT
72 //#define dbg globalSignalLoggers.log
73 
74 static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
75 
76 #define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
77 #define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
78 
79 void
execSTTOR(Signal * signal)80 Backup::execSTTOR(Signal* signal)
81 {
82   jamEntry();
83 
84   const Uint32 startphase  = signal->theData[1];
85   const Uint32 typeOfStart = signal->theData[7];
86 
87   if (startphase == 1)
88   {
89     m_curr_disk_write_speed = c_defaults.m_disk_write_speed_sr;
90     m_overflow_disk_write = 0;
91     m_reset_disk_speed_time = NdbTick_CurrentMillisecond();
92     m_reset_delay_used = Backup::DISK_SPEED_CHECK_DELAY;
93     signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
94     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
95                         Backup::DISK_SPEED_CHECK_DELAY, 1);
96   }
97   if (startphase == 3) {
98     jam();
99     g_TypeOfStart = typeOfStart;
100     signal->theData[0] = reference();
101     sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
102     return;
103   }//if
104 
105   if (startphase == 7)
106   {
107     m_curr_disk_write_speed = c_defaults.m_disk_write_speed;
108   }
109 
110   if(startphase == 7 && g_TypeOfStart == NodeState::ST_INITIAL_START &&
111      c_masterNodeId == getOwnNodeId()){
112     jam();
113     createSequence(signal);
114     return;
115   }//if
116 
117   sendSTTORRY(signal);
118   return;
119 }//Dbdict::execSTTOR()
120 
121 void
execREAD_NODESCONF(Signal * signal)122 Backup::execREAD_NODESCONF(Signal* signal)
123 {
124   jamEntry();
125   ReadNodesConf * conf = (ReadNodesConf *)signal->getDataPtr();
126 
127   c_aliveNodes.clear();
128 
129   Uint32 count = 0;
130   for (Uint32 i = 0; i<MAX_NDB_NODES; i++) {
131     jam();
132     if(NodeBitmask::get(conf->allNodes, i)){
133       jam();
134       count++;
135 
136       NodePtr node;
137       ndbrequire(c_nodes.seize(node));
138 
139       node.p->nodeId = i;
140       if(NodeBitmask::get(conf->inactiveNodes, i)) {
141         jam();
142 	node.p->alive = 0;
143       } else {
144         jam();
145 	node.p->alive = 1;
146 	c_aliveNodes.set(i);
147       }//if
148     }//if
149   }//for
150   c_masterNodeId = conf->masterNodeId;
151   ndbrequire(count == conf->noOfNodes);
152   sendSTTORRY(signal);
153 }
154 
155 void
sendSTTORRY(Signal * signal)156 Backup::sendSTTORRY(Signal* signal)
157 {
158   signal->theData[0] = 0;
159   signal->theData[3] = 1;
160   signal->theData[4] = 3;
161   signal->theData[5] = 7;
162   signal->theData[6] = 255; // No more start phases from missra
163   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
164 }
165 
166 void
createSequence(Signal * signal)167 Backup::createSequence(Signal* signal)
168 {
169   UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
170 
171   req->senderData  = RNIL;
172   req->sequenceId  = BACKUP_SEQUENCE;
173   req->requestType = UtilSequenceReq::Create;
174 
175   sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
176 	     signal, UtilSequenceReq::SignalLength, JBB);
177 }
178 
179 void
execCONTINUEB(Signal * signal)180 Backup::execCONTINUEB(Signal* signal)
181 {
182   jamEntry();
183   const Uint32 Tdata0 = signal->theData[0];
184   const Uint32 Tdata1 = signal->theData[1];
185   const Uint32 Tdata2 = signal->theData[2];
186 
187   switch(Tdata0) {
188   case BackupContinueB::RESET_DISK_SPEED_COUNTER:
189   {
190     /*
191       Adjust for upto 10 millisecond delay of this signal. Longer
192       delays will not be handled, in this case the system is most
193       likely under too high load and it won't matter very much that
194       we decrease the speed of checkpoints.
195 
196       We use a technique where we allow an overflow write in one
197       period. This overflow will be removed from the next period
198       such that the load will at average be as specified.
199     */
200     int delay_time = m_reset_delay_used;
201     NDB_TICKS curr_time = NdbTick_CurrentMillisecond();
202     int sig_delay = curr_time - m_reset_disk_speed_time;
203 
204     m_words_written_this_period = m_overflow_disk_write;
205     m_overflow_disk_write = 0;
206     m_reset_disk_speed_time = curr_time;
207 
208     if (sig_delay > delay_time + 10)
209       delay_time = Backup::DISK_SPEED_CHECK_DELAY - 10;
210     else if (sig_delay < delay_time - 10)
211       delay_time = Backup::DISK_SPEED_CHECK_DELAY + 10;
212     else
213       delay_time = Backup::DISK_SPEED_CHECK_DELAY - (sig_delay - delay_time);
214     m_reset_delay_used= delay_time;
215     signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
216     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, delay_time, 1);
217 #if 0
218     ndbout << "Signal delay was = " << sig_delay;
219     ndbout << " Current time = " << curr_time << endl;
220     ndbout << " Delay time will be = " << delay_time << endl << endl;
221 #endif
222     break;
223   }
224   case BackupContinueB::BACKUP_FRAGMENT_INFO:
225   {
226     jam();
227     const Uint32 ptr_I = Tdata1;
228     Uint32 tabPtr_I = Tdata2;
229     Uint32 fragPtr_I = signal->theData[3];
230 
231     BackupRecordPtr ptr LINT_SET_PTR;
232     c_backupPool.getPtr(ptr, ptr_I);
233     TablePtr tabPtr;
234     ptr.p->tables.getPtr(tabPtr, tabPtr_I);
235 
236     if (fragPtr_I != tabPtr.p->fragments.getSize())
237     {
238       jam();
239       FragmentPtr fragPtr;
240       tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I);
241 
242       BackupFilePtr filePtr LINT_SET_PTR;
243       ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
244 
245       const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2;
246       Uint32 * dst;
247       if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz))
248       {
249 	sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4);
250 	return;
251       }
252 
253       BackupFormat::CtlFile::FragmentInfo * fragInfo =
254 	(BackupFormat::CtlFile::FragmentInfo*)dst;
255       fragInfo->SectionType = htonl(BackupFormat::FRAGMENT_INFO);
256       fragInfo->SectionLength = htonl(sz);
257       fragInfo->TableId = htonl(fragPtr.p->tableId);
258       fragInfo->FragmentNo = htonl(fragPtr_I);
259       fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF);
260       fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32);
261       fragInfo->FilePosLow = htonl(0);
262       fragInfo->FilePosHigh = htonl(0);
263 
264       filePtr.p->operation.dataBuffer.updateWritePtr(sz);
265 
266       fragPtr_I++;
267     }
268 
269     if (fragPtr_I == tabPtr.p->fragments.getSize())
270     {
271       signal->theData[0] = tabPtr.p->tableId;
272       signal->theData[1] = 0; // unlock
273       EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
274 
275       fragPtr_I = 0;
276       ptr.p->tables.next(tabPtr);
277       if ((tabPtr_I = tabPtr.i) == RNIL)
278       {
279 	jam();
280 	closeFiles(signal, ptr);
281 	return;
282       }
283     }
284 
285     signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
286     signal->theData[1] = ptr_I;
287     signal->theData[2] = tabPtr_I;
288     signal->theData[3] = fragPtr_I;
289     sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
290     return;
291   }
292   case BackupContinueB::START_FILE_THREAD:
293   case BackupContinueB::BUFFER_UNDERFLOW:
294   {
295     jam();
296     BackupFilePtr filePtr LINT_SET_PTR;
297     c_backupFilePool.getPtr(filePtr, Tdata1);
298     checkFile(signal, filePtr);
299     return;
300   }
301   break;
302   case BackupContinueB::BUFFER_FULL_SCAN:
303   {
304     jam();
305     BackupFilePtr filePtr LINT_SET_PTR;
306     c_backupFilePool.getPtr(filePtr, Tdata1);
307     checkScan(signal, filePtr);
308     return;
309   }
310   break;
311   case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE:
312   {
313     jam();
314     BackupFilePtr filePtr LINT_SET_PTR;
315     c_backupFilePool.getPtr(filePtr, Tdata1);
316     fragmentCompleted(signal, filePtr);
317     return;
318   }
319   break;
320   case BackupContinueB::BUFFER_FULL_META:
321   {
322     jam();
323     BackupRecordPtr ptr LINT_SET_PTR;
324     c_backupPool.getPtr(ptr, Tdata1);
325 
326     BackupFilePtr filePtr LINT_SET_PTR;
327     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
328     FsBuffer & buf = filePtr.p->operation.dataBuffer;
329 
330     if(buf.getFreeSize() < buf.getMaxWrite()) {
331       jam();
332       TablePtr tabPtr LINT_SET_PTR;
333       c_tablePool.getPtr(tabPtr, Tdata2);
334 
335       DEBUG_OUT("Backup - Buffer full - "
336                 << buf.getFreeSize()
337 		<< " < " << buf.getMaxWrite()
338                 << " (sz: " << buf.getUsableSize()
339                 << " getMinRead: " << buf.getMinRead()
340 		<< ") - tableId = " << tabPtr.p->tableId);
341 
342       signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
343       signal->theData[1] = Tdata1;
344       signal->theData[2] = Tdata2;
345       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
346       return;
347     }//if
348 
349     TablePtr tabPtr LINT_SET_PTR;
350     c_tablePool.getPtr(tabPtr, Tdata2);
351     GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
352     req->senderRef = reference();
353     req->senderData = ptr.i;
354     req->requestType = GetTabInfoReq::RequestById |
355       GetTabInfoReq::LongSignalConf;
356     req->tableId = tabPtr.p->tableId;
357     sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
358 	       GetTabInfoReq::SignalLength, JBB);
359     return;
360   }
361   case BackupContinueB::ZDELAY_SCAN_NEXT:
362     if (ERROR_INSERTED(10036))
363     {
364       jam();
365       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 300,
366 			  signal->getLength());
367       return;
368     }
369     else
370     {
371       jam();
372       CLEAR_ERROR_INSERT_VALUE;
373       ndbout_c("Resuming backup");
374       memmove(signal->theData, signal->theData + 1,
375 	      4*ScanFragNextReq::SignalLength);
376       sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
377 		 ScanFragNextReq::SignalLength, JBB);
378       return ;
379     }
380   default:
381     ndbrequire(0);
382   }//switch
383 }
384 
385 void
execDUMP_STATE_ORD(Signal * signal)386 Backup::execDUMP_STATE_ORD(Signal* signal)
387 {
388   jamEntry();
389 
390   if(signal->theData[0] == 20){
391     if(signal->length() > 1){
392       c_defaults.m_dataBufferSize = (signal->theData[1] * 1024 * 1024);
393     }
394     if(signal->length() > 2){
395       c_defaults.m_logBufferSize = (signal->theData[2] * 1024 * 1024);
396     }
397     if(signal->length() > 3){
398       c_defaults.m_minWriteSize = signal->theData[3] * 1024;
399     }
400     if(signal->length() > 4){
401       c_defaults.m_maxWriteSize = signal->theData[4] * 1024;
402     }
403 
404     infoEvent("Backup: data: %d log: %d min: %d max: %d",
405 	      c_defaults.m_dataBufferSize,
406 	      c_defaults.m_logBufferSize,
407 	      c_defaults.m_minWriteSize,
408 	      c_defaults.m_maxWriteSize);
409     return;
410   }
411   if(signal->theData[0] == 21){
412     BackupReq * req = (BackupReq*)signal->getDataPtrSend();
413     req->senderData = 23;
414     req->backupDataLen = 0;
415     sendSignal(BACKUP_REF, GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
416     startTime = NdbTick_CurrentMillisecond();
417     return;
418   }
419 
420   if(signal->theData[0] == 22){
421     const Uint32 seq = signal->theData[1];
422     FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
423     req->userReference = reference();
424     req->userPointer = 23;
425     req->directory = 1;
426     req->ownDirectory = 1;
427     FsOpenReq::setVersion(req->fileNumber, 2);
428     FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
429     FsOpenReq::v2_setSequence(req->fileNumber, seq);
430     FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
431     sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
432 	       FsRemoveReq::SignalLength, JBA);
433     return;
434   }
435 
436   if(signal->theData[0] == 23){
437     /**
438      * Print records
439      */
440     BackupRecordPtr ptr LINT_SET_PTR;
441     for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){
442       infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x",
443 		ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
444       infoEvent(" State: %d", ptr.p->slaveState.getState());
445       BackupFilePtr filePtr;
446       for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
447 	  ptr.p->files.next(filePtr)){
448 	jam();
449 	infoEvent(" file %d: type: %d flags: H'%x",
450 		  filePtr.i, filePtr.p->fileType,
451 		  filePtr.p->m_flags);
452       }
453     }
454 
455     ndbout_c("m_curr_disk_write_speed: %u  m_words_written_this_period: %u  m_overflow_disk_write: %u",
456               m_curr_disk_write_speed, m_words_written_this_period, m_overflow_disk_write);
457     ndbout_c("m_reset_delay_used: %u  m_reset_disk_speed_time: %llu",
458              m_reset_delay_used, (Uint64)m_reset_disk_speed_time);
459     for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr))
460     {
461       ndbout_c("BackupRecord %u:  BackupId: %u  MasterRef: %x  ClientRef: %x",
462                ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
463       ndbout_c(" State: %u", ptr.p->slaveState.getState());
464       ndbout_c(" noOfByte: %llu  noOfRecords: %llu",
465                ptr.p->noOfBytes, ptr.p->noOfRecords);
466       ndbout_c(" noOfLogBytes: %llu  noOfLogRecords: %llu",
467                ptr.p->noOfLogBytes, ptr.p->noOfLogRecords);
468       ndbout_c(" errorCode: %u", ptr.p->errorCode);
469       BackupFilePtr filePtr;
470       for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
471 	  ptr.p->files.next(filePtr))
472       {
473 	ndbout_c(" file %u:  type: %u  flags: H'%x  tableId: %u  fragmentId: %u",
474                  filePtr.i, filePtr.p->fileType, filePtr.p->m_flags,
475                  filePtr.p->tableId, filePtr.p->fragmentNo);
476       }
477       if (ptr.p->slaveState.getState() == SCANNING && ptr.p->dataFilePtr != RNIL)
478       {
479         c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
480         OperationRecord & op = filePtr.p->operation;
481         Uint32 *tmp = NULL;
482         Uint32 sz = 0;
483         bool eof = FALSE;
484         bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
485         ndbout_c("ready: %s  eof: %s", ready ? "TRUE" : "FALSE", eof ? "TRUE" : "FALSE");
486       }
487     }
488     return;
489   }
490   if(signal->theData[0] == 24){
491     /**
492      * Print size of records etc.
493      */
494     infoEvent("Backup - dump pool sizes");
495     infoEvent("BackupPool: %d BackupFilePool: %d TablePool: %d",
496 	      c_backupPool.getSize(), c_backupFilePool.getSize(),
497 	      c_tablePool.getSize());
498     infoEvent("AttrPool: %d TriggerPool: %d FragmentPool: %d",
499 	      c_backupPool.getSize(), c_backupFilePool.getSize(),
500 	      c_tablePool.getSize());
501     infoEvent("PagePool: %d",
502 	      c_pagePool.getSize());
503 
504 
505     if(signal->getLength() == 2 && signal->theData[1] == 2424)
506     {
507       /**
508        * Handle LCP
509        */
510       BackupRecordPtr lcp;
511       ndbrequire(c_backups.first(lcp));
512 
513       ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree() + 1);
514       if(lcp.p->tables.isEmpty())
515       {
516 	ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree());
517 	ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree());
518 	ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree());
519 	ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree());
520       }
521       ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree() + 1);
522       BackupFilePtr lcp_file;
523       c_backupFilePool.getPtr(lcp_file, lcp.p->dataFilePtr);
524       ndbrequire(c_pagePool.getSize() ==
525 		 c_pagePool.getNoOfFree() +
526 		 lcp_file.p->pages.getSize());
527     }
528   }
529 }
530 
531 bool
findTable(const BackupRecordPtr & ptr,TablePtr & tabPtr,Uint32 tableId) const532 Backup::findTable(const BackupRecordPtr & ptr,
533 		  TablePtr & tabPtr, Uint32 tableId) const
534 {
535   for(ptr.p->tables.first(tabPtr);
536       tabPtr.i != RNIL;
537       ptr.p->tables.next(tabPtr)) {
538     jam();
539     if(tabPtr.p->tableId == tableId){
540       jam();
541       return true;
542     }//if
543   }//for
544   tabPtr.i = RNIL;
545   tabPtr.p = 0;
546   return false;
547 }
548 
xps(Uint64 x,Uint64 ms)549 static Uint32 xps(Uint64 x, Uint64 ms)
550 {
551   float fx = x;
552   float fs = ms;
553 
554   if(ms == 0 || x == 0) {
555     jam();
556     return 0;
557   }//if
558   jam();
559   return ((Uint32)(1000.0f * (fx + fs/2.1f))) / ((Uint32)fs);
560 }
561 
562 struct Number {
NumberNumber563   Number(Uint64 r) { val = r;}
operator =Number564   Number & operator=(Uint64 r) { val = r; return * this; }
565   Uint64 val;
566 };
567 
568 NdbOut &
operator <<(NdbOut & out,const Number & val)569 operator<< (NdbOut & out, const Number & val){
570   char p = 0;
571   Uint32 loop = 1;
572   while(val.val > loop){
573     loop *= 1000;
574     p += 3;
575   }
576   if(loop != 1){
577     p -= 3;
578     loop /= 1000;
579   }
580 
581   switch(p){
582   case 0:
583     break;
584   case 3:
585     p = 'k';
586     break;
587   case 6:
588     p = 'M';
589     break;
590   case 9:
591     p = 'G';
592     break;
593   default:
594     p = 0;
595   }
596   char str[2];
597   str[0] = p;
598   str[1] = 0;
599   Uint32 tmp = (val.val + (loop >> 1)) / loop;
600 #if 1
601   if(p > 0)
602     out << tmp << str;
603   else
604     out << tmp;
605 #else
606   out << val.val;
607 #endif
608 
609   return out;
610 }
611 
612 void
execBACKUP_CONF(Signal * signal)613 Backup::execBACKUP_CONF(Signal* signal)
614 {
615   jamEntry();
616   BackupConf * conf = (BackupConf*)signal->getDataPtr();
617 
618   ndbout_c("Backup %d has started", conf->backupId);
619 }
620 
621 void
execBACKUP_REF(Signal * signal)622 Backup::execBACKUP_REF(Signal* signal)
623 {
624   jamEntry();
625   BackupRef * ref = (BackupRef*)signal->getDataPtr();
626 
627   ndbout_c("Backup (%d) has NOT started %d", ref->senderData, ref->errorCode);
628 }
629 
630 void
execBACKUP_COMPLETE_REP(Signal * signal)631 Backup::execBACKUP_COMPLETE_REP(Signal* signal)
632 {
633   jamEntry();
634   BackupCompleteRep* rep = (BackupCompleteRep*)signal->getDataPtr();
635 
636   startTime = NdbTick_CurrentMillisecond() - startTime;
637 
638   ndbout_c("Backup %d has completed", rep->backupId);
639   const Uint64 bytes =
640     rep->noOfBytesLow + (((Uint64)rep->noOfBytesHigh) << 32);
641   const Uint64 records =
642     rep->noOfRecordsLow + (((Uint64)rep->noOfRecordsHigh) << 32);
643 
644   Number rps = xps(records, startTime);
645   Number bps = xps(bytes, startTime);
646 
647   ndbout << " Data [ "
648 	 << Number(records) << " rows "
649 	 << Number(bytes) << " bytes " << startTime << " ms ] "
650 	 << " => "
651 	 << rps << " row/s & " << bps << "b/s" << endl;
652 
653   bps = xps(rep->noOfLogBytes, startTime);
654   rps = xps(rep->noOfLogRecords, startTime);
655 
656   ndbout << " Log [ "
657 	 << Number(rep->noOfLogRecords) << " log records "
658 	 << Number(rep->noOfLogBytes) << " bytes " << startTime << " ms ] "
659 	 << " => "
660 	 << rps << " records/s & " << bps << "b/s" << endl;
661 
662 }
663 
664 void
execBACKUP_ABORT_REP(Signal * signal)665 Backup::execBACKUP_ABORT_REP(Signal* signal)
666 {
667   jamEntry();
668   BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtr();
669 
670   ndbout_c("Backup %d has been aborted %d", rep->backupId, rep->reason);
671 }
672 
673 const TriggerEvent::Value triggerEventValues[] = {
674   TriggerEvent::TE_INSERT,
675   TriggerEvent::TE_UPDATE,
676   TriggerEvent::TE_DELETE
677 };
678 
679 const Backup::State
680 Backup::validSlaveTransitions[] = {
681   INITIAL,  DEFINING,
682   DEFINING, DEFINED,
683   DEFINED,  STARTED,
684   STARTED,  STARTED, // Several START_BACKUP_REQ is sent
685   STARTED,  SCANNING,
686   SCANNING, STARTED,
687   STARTED,  STOPPING,
688   STOPPING, CLEANING,
689   CLEANING, INITIAL,
690 
691   INITIAL,  ABORTING, // Node fail
692   DEFINING, ABORTING,
693   DEFINED,  ABORTING,
694   STARTED,  ABORTING,
695   SCANNING, ABORTING,
696   STOPPING, ABORTING,
697   CLEANING, ABORTING, // Node fail w/ master takeover
698   ABORTING, ABORTING, // Slave who initiates ABORT should have this transition
699 
700   ABORTING, INITIAL,
701   INITIAL,  INITIAL
702 };
703 
704 const Uint32
705 Backup::validSlaveTransitionsCount =
706 sizeof(Backup::validSlaveTransitions) / sizeof(Backup::State);
707 
708 void
setState(State newState)709 Backup::CompoundState::setState(State newState){
710   bool found = false;
711   const State currState = state;
712   for(unsigned i = 0; i<noOfValidTransitions; i+= 2) {
713     jam();
714     if(validTransitions[i]   == currState &&
715        validTransitions[i+1] == newState){
716       jam();
717       found = true;
718       break;
719     }
720   }
721 
722   //ndbrequire(found);
723 
724   if (newState == INITIAL)
725     abortState = INITIAL;
726   if(newState == ABORTING && currState != ABORTING) {
727     jam();
728     abortState = currState;
729   }
730   state = newState;
731 #ifdef DEBUG_ABORT
732   if (newState != currState) {
733     ndbout_c("%u: Old state = %u, new state = %u, abort state = %u",
734 	     id, currState, newState, abortState);
735   }
736 #endif
737 }
738 
739 void
forceState(State newState)740 Backup::CompoundState::forceState(State newState)
741 {
742   const State currState = state;
743   if (newState == INITIAL)
744     abortState = INITIAL;
745   if(newState == ABORTING && currState != ABORTING) {
746     jam();
747     abortState = currState;
748   }
749   state = newState;
750 #ifdef DEBUG_ABORT
751   if (newState != currState) {
752     ndbout_c("%u: FORCE: Old state = %u, new state = %u, abort state = %u",
753 	     id, currState, newState, abortState);
754   }
755 #endif
756 }
757 
Table(ArrayPool<Attribute> & ah,ArrayPool<Fragment> & fh)758 Backup::Table::Table(ArrayPool<Attribute> & ah,
759 		     ArrayPool<Fragment> & fh)
760   : attributes(ah), fragments(fh)
761 {
762   triggerIds[0] = ILLEGAL_TRIGGER_ID;
763   triggerIds[1] = ILLEGAL_TRIGGER_ID;
764   triggerIds[2] = ILLEGAL_TRIGGER_ID;
765   triggerAllocated[0] = false;
766   triggerAllocated[1] = false;
767   triggerAllocated[2] = false;
768 }
769 
770 /*****************************************************************************
771  *
772  * Node state handling
773  *
774  *****************************************************************************/
775 void
execNODE_FAILREP(Signal * signal)776 Backup::execNODE_FAILREP(Signal* signal)
777 {
778   jamEntry();
779 
780   NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
781 
782   bool doStuff = false;
783   /*
784   Start by saving important signal data which will be destroyed before the
785   process is completed.
786   */
787   NodeId new_master_node_id = rep->masterNodeId;
788   Uint32 theFailedNodes[NodeBitmask::Size];
789   for (Uint32 i = 0; i < NodeBitmask::Size; i++)
790     theFailedNodes[i] = rep->theNodes[i];
791 
792   c_masterNodeId = new_master_node_id;
793 
794   NodePtr nodePtr;
795   for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
796     jam();
797     if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)){
798       if(nodePtr.p->alive){
799 	jam();
800 	ndbrequire(c_aliveNodes.get(nodePtr.p->nodeId));
801 	doStuff = true;
802       } else {
803         jam();
804 	ndbrequire(!c_aliveNodes.get(nodePtr.p->nodeId));
805       }//if
806       nodePtr.p->alive = 0;
807       c_aliveNodes.clear(nodePtr.p->nodeId);
808     }//if
809   }//for
810 
811   if(!doStuff){
812     jam();
813     return;
814   }//if
815 
816 #ifdef DEBUG_ABORT
817   ndbout_c("****************** Node fail rep ******************");
818 #endif
819 
820   NodeId newCoordinator = c_masterNodeId;
821   BackupRecordPtr ptr;
822   for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
823     jam();
824     checkNodeFail(signal, ptr, newCoordinator, theFailedNodes);
825   }
826 }
827 
828 bool
verifyNodesAlive(BackupRecordPtr ptr,const NdbNodeBitmask & aNodeBitMask)829 Backup::verifyNodesAlive(BackupRecordPtr ptr,
830 			 const NdbNodeBitmask& aNodeBitMask)
831 {
832   Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
833   for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
834     jam();
835     if(aNodeBitMask.get(i)) {
836       if(!c_aliveNodes.get(i)){
837         jam();
838 	ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
839         return false;
840       }//if
841       if(getNodeInfo(i).m_version != version)
842       {
843 	jam();
844 	ptr.p->setErrorCode(AbortBackupOrd::IncompatibleVersions);
845 	return false;
846       }
847     }//if
848   }//for
849   return true;
850 }
851 
852 void
checkNodeFail(Signal * signal,BackupRecordPtr ptr,NodeId newCoord,Uint32 theFailedNodes[NodeBitmask::Size])853 Backup::checkNodeFail(Signal* signal,
854 		      BackupRecordPtr ptr,
855 		      NodeId newCoord,
856 		      Uint32 theFailedNodes[NodeBitmask::Size])
857 {
858   NdbNodeBitmask mask;
859   mask.assign(2, theFailedNodes);
860 
861   /* Update ptr.p->nodes to be up to date with current alive nodes
862    */
863   NodePtr nodePtr;
864   bool found = false;
865   for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
866     jam();
867     if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)) {
868       jam();
869       if (ptr.p->nodes.get(nodePtr.p->nodeId)) {
870 	jam();
871 	ptr.p->nodes.clear(nodePtr.p->nodeId);
872 	found = true;
873       }
874     }//if
875   }//for
876 
877   if(!found) {
878     jam();
879     return; // failed node is not part of backup process, safe to continue
880   }
881 
882   if(mask.get(refToNode(ptr.p->masterRef)))
883   {
884     /**
885      * Master died...abort
886      */
887     ptr.p->masterRef = reference();
888     ptr.p->nodes.clear();
889     ptr.p->nodes.set(getOwnNodeId());
890     ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
891     switch(ptr.p->m_gsn){
892     case GSN_DEFINE_BACKUP_REQ:
893     case GSN_START_BACKUP_REQ:
894     case GSN_BACKUP_FRAGMENT_REQ:
895     case GSN_STOP_BACKUP_REQ:
896       // I'm currently processing...reply to self and abort...
897       ptr.p->masterData.gsn = ptr.p->m_gsn;
898       ptr.p->masterData.sendCounter = ptr.p->nodes;
899       return;
900     case GSN_DEFINE_BACKUP_REF:
901     case GSN_DEFINE_BACKUP_CONF:
902     case GSN_START_BACKUP_REF:
903     case GSN_START_BACKUP_CONF:
904     case GSN_BACKUP_FRAGMENT_REF:
905     case GSN_BACKUP_FRAGMENT_CONF:
906     case GSN_STOP_BACKUP_REF:
907     case GSN_STOP_BACKUP_CONF:
908       ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
909       masterAbort(signal, ptr);
910       return;
911     case GSN_ABORT_BACKUP_ORD:
912       // Already aborting
913       return;
914     }
915   }
916   else if (newCoord == getOwnNodeId())
917   {
918     /**
919      * I'm master for this backup
920      */
921     jam();
922     CRASH_INSERTION((10001));
923 #ifdef DEBUG_ABORT
924     ndbout_c("**** Master: Node failed: Master id = %u",
925 	     refToNode(ptr.p->masterRef));
926 #endif
927 
928     Uint32 gsn, len, pos;
929     LINT_INIT(gsn);
930     LINT_INIT(len);
931     LINT_INIT(pos);
932     ptr.p->nodes.bitANDC(mask);
933     switch(ptr.p->masterData.gsn){
934     case GSN_DEFINE_BACKUP_REQ:
935     {
936       DefineBackupRef * ref = (DefineBackupRef*)signal->getDataPtr();
937       ref->backupPtr = ptr.i;
938       ref->backupId = ptr.p->backupId;
939       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
940       gsn= GSN_DEFINE_BACKUP_REF;
941       len= DefineBackupRef::SignalLength;
942       pos= &ref->nodeId - signal->getDataPtr();
943       break;
944     }
945     case GSN_START_BACKUP_REQ:
946     {
947       StartBackupRef * ref = (StartBackupRef*)signal->getDataPtr();
948       ref->backupPtr = ptr.i;
949       ref->backupId = ptr.p->backupId;
950       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
951       gsn= GSN_START_BACKUP_REF;
952       len= StartBackupRef::SignalLength;
953       pos= &ref->nodeId - signal->getDataPtr();
954       break;
955     }
956     case GSN_BACKUP_FRAGMENT_REQ:
957     {
958       BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
959       ref->backupPtr = ptr.i;
960       ref->backupId = ptr.p->backupId;
961       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
962       gsn= GSN_BACKUP_FRAGMENT_REF;
963       len= BackupFragmentRef::SignalLength;
964       pos= &ref->nodeId - signal->getDataPtr();
965       break;
966     }
967     case GSN_STOP_BACKUP_REQ:
968     {
969       StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
970       ref->backupPtr = ptr.i;
971       ref->backupId = ptr.p->backupId;
972       ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
973       ref->nodeId = getOwnNodeId();
974       gsn= GSN_STOP_BACKUP_REF;
975       len= StopBackupRef::SignalLength;
976       pos= &ref->nodeId - signal->getDataPtr();
977       break;
978     }
979     case GSN_WAIT_GCP_REQ:
980     case GSN_DROP_TRIG_REQ:
981     case GSN_CREATE_TRIG_REQ:
982     case GSN_ALTER_TRIG_REQ:
983       ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
984       return;
985     case GSN_UTIL_SEQUENCE_REQ:
986     case GSN_UTIL_LOCK_REQ:
987       return;
988     default:
989       ndbrequire(false);
990     }
991 
992     for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; )
993     {
994       signal->theData[pos] = i;
995       sendSignal(reference(), gsn, signal, len, JBB);
996 #ifdef DEBUG_ABORT
997       ndbout_c("sending %d to self from %d", gsn, i);
998 #endif
999     }
1000     return;
1001   }//if
1002 
1003   /**
1004    * I abort myself as slave if not master
1005    */
1006   CRASH_INSERTION((10021));
1007 }
1008 
1009 void
execINCL_NODEREQ(Signal * signal)1010 Backup::execINCL_NODEREQ(Signal* signal)
1011 {
1012   jamEntry();
1013 
1014   const Uint32 senderRef = signal->theData[0];
1015   const Uint32 inclNode  = signal->theData[1];
1016 
1017   NodePtr node;
1018   for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
1019     jam();
1020     const Uint32 nodeId = node.p->nodeId;
1021     if(inclNode == nodeId){
1022       jam();
1023 
1024       ndbrequire(node.p->alive == 0);
1025       ndbrequire(!c_aliveNodes.get(nodeId));
1026 
1027       node.p->alive = 1;
1028       c_aliveNodes.set(nodeId);
1029 
1030       break;
1031     }//if
1032   }//for
1033   signal->theData[0] = inclNode;
1034   signal->theData[1] = reference();
1035   sendSignal(senderRef, GSN_INCL_NODECONF, signal, 2, JBB);
1036 }
1037 
1038 /*****************************************************************************
1039  *
1040  * Master functionallity - Define backup
1041  *
1042  *****************************************************************************/
1043 
1044 void
execBACKUP_REQ(Signal * signal)1045 Backup::execBACKUP_REQ(Signal* signal)
1046 {
1047   jamEntry();
1048   BackupReq * req = (BackupReq*)signal->getDataPtr();
1049 
1050   const Uint32 senderData = req->senderData;
1051   const BlockReference senderRef = signal->senderBlockRef();
1052   const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
1053   const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
1054 
1055   if(getOwnNodeId() != getMasterNodeId()) {
1056     jam();
1057     sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
1058     return;
1059   }//if
1060 
1061   if (c_defaults.m_diskless)
1062   {
1063     sendBackupRef(senderRef, flags, signal, senderData,
1064 		  BackupRef::CannotBackupDiskless);
1065     return;
1066   }
1067 
1068   if(dataLen32 != 0) {
1069     jam();
1070     sendBackupRef(senderRef, flags, signal, senderData,
1071 		  BackupRef::BackupDefinitionNotImplemented);
1072     return;
1073   }//if
1074 
1075 #ifdef DEBUG_ABORT
1076   dumpUsedResources();
1077 #endif
1078   /**
1079    * Seize a backup record
1080    */
1081   BackupRecordPtr ptr;
1082   c_backups.seize(ptr);
1083   if(ptr.i == RNIL) {
1084     jam();
1085     sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
1086     return;
1087   }//if
1088 
1089   ndbrequire(ptr.p->tables.isEmpty());
1090 
1091   ptr.p->m_gsn = 0;
1092   ptr.p->errorCode = 0;
1093   ptr.p->clientRef = senderRef;
1094   ptr.p->clientData = senderData;
1095   ptr.p->flags = flags;
1096   ptr.p->masterRef = reference();
1097   ptr.p->nodes = c_aliveNodes;
1098   ptr.p->backupId = 0;
1099   ptr.p->backupKey[0] = 0;
1100   ptr.p->backupKey[1] = 0;
1101   ptr.p->backupDataLen = 0;
1102   ptr.p->masterData.errorCode = 0;
1103 
1104   UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
1105 
1106   ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ;
1107   utilReq->senderData  = ptr.i;
1108   utilReq->sequenceId  = BACKUP_SEQUENCE;
1109   utilReq->requestType = UtilSequenceReq::NextVal;
1110   sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
1111 	     signal, UtilSequenceReq::SignalLength, JBB);
1112 }
1113 
1114 void
execUTIL_SEQUENCE_REF(Signal * signal)1115 Backup::execUTIL_SEQUENCE_REF(Signal* signal)
1116 {
1117   BackupRecordPtr ptr LINT_SET_PTR;
1118   jamEntry();
1119   UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr();
1120   ptr.i = utilRef->senderData;
1121   c_backupPool.getPtr(ptr);
1122   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
1123   sendBackupRef(signal, ptr, BackupRef::SequenceFailure);
1124 }//execUTIL_SEQUENCE_REF()
1125 
1126 
1127 void
sendBackupRef(Signal * signal,BackupRecordPtr ptr,Uint32 errorCode)1128 Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
1129 {
1130   jam();
1131   sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
1132   cleanup(signal, ptr);
1133 }
1134 
1135 void
sendBackupRef(BlockReference senderRef,Uint32 flags,Signal * signal,Uint32 senderData,Uint32 errorCode)1136 Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
1137 		      Uint32 senderData, Uint32 errorCode)
1138 {
1139   jam();
1140   if (SEND_BACKUP_STARTED_FLAG(flags))
1141   {
1142     BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
1143     ref->senderData = senderData;
1144     ref->errorCode = errorCode;
1145     ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
1146     sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
1147   }
1148 
1149   if(errorCode != BackupRef::IAmNotMaster){
1150     signal->theData[0] = NDB_LE_BackupFailedToStart;
1151     signal->theData[1] = senderRef;
1152     signal->theData[2] = errorCode;
1153     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
1154   }
1155 }
1156 
1157 void
execUTIL_SEQUENCE_CONF(Signal * signal)1158 Backup::execUTIL_SEQUENCE_CONF(Signal* signal)
1159 {
1160   jamEntry();
1161 
1162   UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
1163 
1164   if(conf->requestType == UtilSequenceReq::Create)
1165   {
1166     jam();
1167     sendSTTORRY(signal); // At startup in NDB
1168     return;
1169   }
1170 
1171   BackupRecordPtr ptr LINT_SET_PTR;
1172   ptr.i = conf->senderData;
1173   c_backupPool.getPtr(ptr);
1174 
1175   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
1176 
1177   if (ptr.p->checkError())
1178   {
1179     jam();
1180     sendBackupRef(signal, ptr, ptr.p->errorCode);
1181     return;
1182   }//if
1183 
1184   if (ERROR_INSERTED(10023))
1185   {
1186     sendBackupRef(signal, ptr, 323);
1187     return;
1188   }//if
1189 
1190 
1191   {
1192     Uint64 backupId;
1193     memcpy(&backupId,conf->sequenceValue,8);
1194     ptr.p->backupId= (Uint32)backupId;
1195   }
1196   ptr.p->backupKey[0] = (getOwnNodeId() << 16) | (ptr.p->backupId & 0xFFFF);
1197   ptr.p->backupKey[1] = NdbTick_CurrentMillisecond();
1198 
1199   ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
1200   Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1201   Callback c = { safe_cast(&Backup::defineBackupMutex_locked), ptr.i };
1202   ndbrequire(mutex.lock(c));
1203 
1204   return;
1205 }
1206 
1207 void
defineBackupMutex_locked(Signal * signal,Uint32 ptrI,Uint32 retVal)1208 Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
1209   jamEntry();
1210   ndbrequire(retVal == 0);
1211 
1212   BackupRecordPtr ptr LINT_SET_PTR;
1213   ptr.i = ptrI;
1214   c_backupPool.getPtr(ptr);
1215 
1216   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
1217 
1218   ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
1219   Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1220   Callback c = { safe_cast(&Backup::dictCommitTableMutex_locked), ptr.i };
1221   ndbrequire(mutex.lock(c));
1222 }
1223 
1224 void
dictCommitTableMutex_locked(Signal * signal,Uint32 ptrI,Uint32 retVal)1225 Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal)
1226 {
1227   jamEntry();
1228   ndbrequire(retVal == 0);
1229 
1230   /**
1231    * We now have both the mutexes
1232    */
1233   BackupRecordPtr ptr LINT_SET_PTR;
1234   ptr.i = ptrI;
1235   c_backupPool.getPtr(ptr);
1236 
1237   ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
1238 
1239   if (ERROR_INSERTED(10031)) {
1240     ptr.p->setErrorCode(331);
1241   }//if
1242 
1243   if (ptr.p->checkError())
1244   {
1245     jam();
1246 
1247     /**
1248      * Unlock mutexes
1249      */
1250     jam();
1251     Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1252     jam();
1253     mutex1.unlock(); // ignore response
1254 
1255     jam();
1256     Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1257     jam();
1258     mutex2.unlock(); // ignore response
1259 
1260     sendBackupRef(signal, ptr, ptr.p->errorCode);
1261     return;
1262   }//if
1263 
1264   sendDefineBackupReq(signal, ptr);
1265 }
1266 
1267 /*****************************************************************************
1268  *
1269  * Master functionallity - Define backup cont'd (from now on all slaves are in)
1270  *
1271  *****************************************************************************/
1272 
1273 bool
haveAllSignals(BackupRecordPtr ptr,Uint32 gsn,Uint32 nodeId)1274 Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId)
1275 {
1276   ndbrequire(ptr.p->masterRef == reference());
1277   ndbrequire(ptr.p->masterData.gsn == gsn);
1278   ndbrequire(!ptr.p->masterData.sendCounter.done());
1279   ndbrequire(ptr.p->masterData.sendCounter.isWaitingFor(nodeId));
1280 
1281   ptr.p->masterData.sendCounter.clearWaitingFor(nodeId);
1282   return ptr.p->masterData.sendCounter.done();
1283 }
1284 
1285 void
sendDefineBackupReq(Signal * signal,BackupRecordPtr ptr)1286 Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
1287 {
1288   /**
1289    * Sending define backup to all participants
1290    */
1291   DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
1292   req->backupId = ptr.p->backupId;
1293   req->clientRef = ptr.p->clientRef;
1294   req->clientData = ptr.p->clientData;
1295   req->senderRef = reference();
1296   req->backupPtr = ptr.i;
1297   req->backupKey[0] = ptr.p->backupKey[0];
1298   req->backupKey[1] = ptr.p->backupKey[1];
1299   req->nodes = ptr.p->nodes;
1300   req->backupDataLen = ptr.p->backupDataLen;
1301   req->flags = ptr.p->flags;
1302 
1303   ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
1304   ptr.p->masterData.sendCounter = ptr.p->nodes;
1305   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1306   sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal,
1307 	     DefineBackupReq::SignalLength, JBB);
1308 
1309   /**
1310    * Now send backup data
1311    */
1312   const Uint32 len = ptr.p->backupDataLen;
1313   if(len == 0){
1314     /**
1315      * No data to send
1316      */
1317     jam();
1318     return;
1319   }//if
1320 
1321   /**
1322    * Not implemented
1323    */
1324   ndbrequire(0);
1325 }
1326 
1327 void
execDEFINE_BACKUP_REF(Signal * signal)1328 Backup::execDEFINE_BACKUP_REF(Signal* signal)
1329 {
1330   jamEntry();
1331 
1332   DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtr();
1333 
1334   const Uint32 ptrI = ref->backupPtr;
1335   //const Uint32 backupId = ref->backupId;
1336   const Uint32 nodeId = ref->nodeId;
1337 
1338   BackupRecordPtr ptr LINT_SET_PTR;
1339   c_backupPool.getPtr(ptr, ptrI);
1340 
1341   ptr.p->setErrorCode(ref->errorCode);
1342   defineBackupReply(signal, ptr, nodeId);
1343 }
1344 
1345 void
execDEFINE_BACKUP_CONF(Signal * signal)1346 Backup::execDEFINE_BACKUP_CONF(Signal* signal)
1347 {
1348   jamEntry();
1349 
1350   DefineBackupConf* conf = (DefineBackupConf*)signal->getDataPtr();
1351   const Uint32 ptrI = conf->backupPtr;
1352   //const Uint32 backupId = conf->backupId;
1353   const Uint32 nodeId = refToNode(signal->senderBlockRef());
1354 
1355   BackupRecordPtr ptr LINT_SET_PTR;
1356   c_backupPool.getPtr(ptr, ptrI);
1357 
1358   if (ERROR_INSERTED(10024))
1359   {
1360     ptr.p->setErrorCode(324);
1361   }
1362 
1363   defineBackupReply(signal, ptr, nodeId);
1364 }
1365 
1366 void
defineBackupReply(Signal * signal,BackupRecordPtr ptr,Uint32 nodeId)1367 Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
1368 {
1369   if (!haveAllSignals(ptr, GSN_DEFINE_BACKUP_REQ, nodeId)) {
1370     jam();
1371     return;
1372   }
1373 
1374   /**
1375    * Unlock mutexes
1376    */
1377   jam();
1378   Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1379   jam();
1380   mutex1.unlock(); // ignore response
1381 
1382   jam();
1383   Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1384   jam();
1385   mutex2.unlock(); // ignore response
1386 
1387   if(ptr.p->checkError())
1388   {
1389     jam();
1390     masterAbort(signal, ptr);
1391     return;
1392   }
1393 
1394   /**
1395    * Reply to client
1396    */
1397   CRASH_INSERTION((10034));
1398 
1399   if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
1400   {
1401     BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
1402     conf->backupId = ptr.p->backupId;
1403     conf->senderData = ptr.p->clientData;
1404     conf->nodes = ptr.p->nodes;
1405     sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
1406 	       BackupConf::SignalLength, JBB);
1407   }
1408 
1409   signal->theData[0] = NDB_LE_BackupStarted;
1410   signal->theData[1] = ptr.p->clientRef;
1411   signal->theData[2] = ptr.p->backupId;
1412   ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
1413   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
1414 
1415   /**
1416    * We've received GSN_DEFINE_BACKUP_CONF from all participants.
1417    *
1418    * Our next step is to send START_BACKUP_REQ to all participants,
1419    * who will then send CREATE_TRIG_REQ for all tables to their local
1420    * DBTUP.
1421    */
1422   TablePtr tabPtr;
1423   ptr.p->tables.first(tabPtr);
1424 
1425   sendStartBackup(signal, ptr, tabPtr);
1426 }
1427 
1428 /*****************************************************************************
1429  *
1430  * Master functionallity - Prepare triggers
1431  *
1432  *****************************************************************************/
1433 void
createAttributeMask(TablePtr tabPtr,Bitmask<MAXNROFATTRIBUTESINWORDS> & mask)1434 Backup::createAttributeMask(TablePtr tabPtr,
1435 			    Bitmask<MAXNROFATTRIBUTESINWORDS> & mask)
1436 {
1437   mask.clear();
1438   Table & table = * tabPtr.p;
1439   Ptr<Attribute> attrPtr;
1440   table.attributes.first(attrPtr);
1441   for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
1442   {
1443     jam();
1444     mask.set(attrPtr.p->data.attrId);
1445   }
1446 }
1447 
1448 void
sendCreateTrig(Signal * signal,BackupRecordPtr ptr,TablePtr tabPtr)1449 Backup::sendCreateTrig(Signal* signal,
1450 			   BackupRecordPtr ptr, TablePtr tabPtr)
1451 {
1452   CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend();
1453 
1454   /*
1455    * First, setup the structures
1456    */
1457   for(Uint32 j=0; j<3; j++) {
1458     jam();
1459 
1460     TriggerPtr trigPtr;
1461     if(!ptr.p->triggers.seize(trigPtr)) {
1462       jam();
1463       ptr.p->m_gsn = GSN_START_BACKUP_REF;
1464       StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
1465       ref->backupPtr = ptr.i;
1466       ref->backupId = ptr.p->backupId;
1467       ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
1468       ref->nodeId = getOwnNodeId();
1469       sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
1470 		 StartBackupRef::SignalLength, JBB);
1471       return;
1472     } // if
1473 
1474     const Uint32 triggerId= trigPtr.i;
1475     tabPtr.p->triggerIds[j] = triggerId;
1476     tabPtr.p->triggerAllocated[j] = true;
1477     trigPtr.p->backupPtr = ptr.i;
1478     trigPtr.p->tableId = tabPtr.p->tableId;
1479     trigPtr.p->tab_ptr_i = tabPtr.i;
1480     trigPtr.p->logEntry = 0;
1481     trigPtr.p->event = j;
1482     trigPtr.p->maxRecordSize = 4096;
1483     trigPtr.p->operation =
1484       &ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
1485     trigPtr.p->operation->noOfBytes = 0;
1486     trigPtr.p->operation->noOfRecords = 0;
1487     trigPtr.p->errorCode = 0;
1488   } // for
1489 
1490   /*
1491    * now ask DBTUP to create
1492    */
1493   ptr.p->slaveData.gsn = GSN_CREATE_TRIG_REQ;
1494   ptr.p->slaveData.trigSendCounter = 3;
1495   ptr.p->slaveData.createTrig.tableId = tabPtr.p->tableId;
1496 
1497   req->setUserRef(reference());
1498   req->setReceiverRef(reference());
1499   req->setConnectionPtr(ptr.i);
1500   req->setRequestType(CreateTrigReq::RT_USER);
1501 
1502   Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask;
1503   createAttributeMask(tabPtr, attrMask);
1504   req->setAttributeMask(attrMask);
1505   req->setTableId(tabPtr.p->tableId);
1506   req->setIndexId(RNIL);        // not used
1507   req->setTriggerType(TriggerType::SUBSCRIPTION);
1508   req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
1509   req->setMonitorReplicas(true);
1510   req->setMonitorAllAttributes(false);
1511   req->setOnline(true);
1512 
1513   for (int i=0; i < 3; i++) {
1514     req->setTriggerId(tabPtr.p->triggerIds[i]);
1515     req->setTriggerEvent(triggerEventValues[i]);
1516 
1517     sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
1518 	       signal, CreateTrigReq::SignalLength, JBB);
1519   }
1520 }
1521 
1522 void
execCREATE_TRIG_CONF(Signal * signal)1523 Backup::execCREATE_TRIG_CONF(Signal* signal)
1524 {
1525   jamEntry();
1526   CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtr();
1527 
1528   const Uint32 ptrI = conf->getConnectionPtr();
1529   const Uint32 tableId = conf->getTableId();
1530   const TriggerEvent::Value type = conf->getTriggerEvent();
1531 
1532   BackupRecordPtr ptr LINT_SET_PTR;
1533   c_backupPool.getPtr(ptr, ptrI);
1534 
1535   /**
1536    * Verify that I'm waiting for this conf
1537    *
1538    * ptr.p->masterRef != reference()
1539    * as slaves and masters have triggers now.
1540    */
1541   ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
1542   ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
1543   ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
1544 
1545   TablePtr tabPtr;
1546   ndbrequire(findTable(ptr, tabPtr, tableId));
1547   ndbrequire(type < 3); // if some decides to change the enums
1548 
1549   createTrigReply(signal, ptr);
1550 }
1551 
1552 void
execCREATE_TRIG_REF(Signal * signal)1553 Backup::execCREATE_TRIG_REF(Signal* signal)
1554 {
1555   jamEntry();
1556   CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr();
1557 
1558   const Uint32 ptrI = ref->getConnectionPtr();
1559   const Uint32 tableId = ref->getTableId();
1560 
1561   BackupRecordPtr ptr LINT_SET_PTR;
1562   c_backupPool.getPtr(ptr, ptrI);
1563 
1564   /**
1565    * Verify that I'm waiting for this ref
1566    *
1567    * ptr.p->masterRef != reference()
1568    * as slaves and masters have triggers now
1569    */
1570   ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
1571   ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
1572   ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
1573 
1574   ptr.p->setErrorCode(ref->getErrorCode());
1575 
1576   createTrigReply(signal, ptr);
1577 }
1578 
1579 void
createTrigReply(Signal * signal,BackupRecordPtr ptr)1580 Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
1581 {
1582   CRASH_INSERTION(10003);
1583 
1584   /**
1585    * Check finished with table
1586    */
1587   ptr.p->slaveData.trigSendCounter--;
1588   if(ptr.p->slaveData.trigSendCounter.done() == false){
1589     jam();
1590     return;
1591   }//if
1592 
1593   if (ERROR_INSERTED(10025))
1594   {
1595     ptr.p->errorCode = 325;
1596   }
1597 
1598   if(ptr.p->checkError()) {
1599     jam();
1600     ptr.p->m_gsn = GSN_START_BACKUP_REF;
1601     StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
1602     ref->backupPtr = ptr.i;
1603     ref->backupId = ptr.p->backupId;
1604     ref->errorCode = ptr.p->errorCode;
1605     ref->nodeId = getOwnNodeId();
1606     sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
1607                StartBackupRef::SignalLength, JBB);
1608     return;
1609   }//if
1610 
1611   TablePtr tabPtr;
1612   ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.createTrig.tableId));
1613 
1614   /**
1615    * Next table
1616    */
1617   ptr.p->tables.next(tabPtr);
1618   if(tabPtr.i != RNIL){
1619     jam();
1620     sendCreateTrig(signal, ptr, tabPtr);
1621     return;
1622   }//if
1623 
1624   /**
1625    * We've finished creating triggers.
1626    *
1627    * send conf and wait
1628    */
1629   ptr.p->m_gsn = GSN_START_BACKUP_CONF;
1630   StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend();
1631   conf->backupPtr = ptr.i;
1632   conf->backupId = ptr.p->backupId;
1633   sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal,
1634 	     StartBackupConf::SignalLength, JBB);
1635 }
1636 
1637 /*****************************************************************************
1638  *
1639  * Master functionallity - Start backup
1640  *
1641  *****************************************************************************/
1642 void
sendStartBackup(Signal * signal,BackupRecordPtr ptr,TablePtr tabPtr)1643 Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
1644 {
1645 
1646   ptr.p->masterData.startBackup.tablePtr = tabPtr.i;
1647 
1648   StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend();
1649   req->backupId = ptr.p->backupId;
1650   req->backupPtr = ptr.i;
1651 
1652   /**
1653    * We use trigger Ids that are unique to BACKUP.
1654    * These don't interfere with other triggers (e.g. from DBDICT)
1655    * as there is a special case in DBTUP.
1656    *
1657    * Consequently, backups during online upgrade won't work
1658    */
1659   ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
1660   ptr.p->masterData.sendCounter = ptr.p->nodes;
1661   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1662   sendSignal(rg, GSN_START_BACKUP_REQ, signal,
1663 	     StartBackupReq::SignalLength, JBB);
1664 }
1665 
1666 void
execSTART_BACKUP_REF(Signal * signal)1667 Backup::execSTART_BACKUP_REF(Signal* signal)
1668 {
1669   jamEntry();
1670 
1671   StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr();
1672   const Uint32 ptrI = ref->backupPtr;
1673   //const Uint32 backupId = ref->backupId;
1674   const Uint32 nodeId = ref->nodeId;
1675 
1676   BackupRecordPtr ptr LINT_SET_PTR;
1677   c_backupPool.getPtr(ptr, ptrI);
1678 
1679   ptr.p->setErrorCode(ref->errorCode);
1680   startBackupReply(signal, ptr, nodeId);
1681 }
1682 
1683 void
execSTART_BACKUP_CONF(Signal * signal)1684 Backup::execSTART_BACKUP_CONF(Signal* signal)
1685 {
1686   jamEntry();
1687 
1688   StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr();
1689   const Uint32 ptrI = conf->backupPtr;
1690   //const Uint32 backupId = conf->backupId;
1691   const Uint32 nodeId = refToNode(signal->senderBlockRef());
1692 
1693   BackupRecordPtr ptr LINT_SET_PTR;
1694   c_backupPool.getPtr(ptr, ptrI);
1695 
1696   startBackupReply(signal, ptr, nodeId);
1697 }
1698 
1699 void
startBackupReply(Signal * signal,BackupRecordPtr ptr,Uint32 nodeId)1700 Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
1701 {
1702 
1703   CRASH_INSERTION((10004));
1704 
1705   if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) {
1706     jam();
1707     return;
1708   }
1709 
1710   if (ERROR_INSERTED(10026))
1711   {
1712     ptr.p->errorCode = 326;
1713   }
1714 
1715   if(ptr.p->checkError()){
1716     jam();
1717     masterAbort(signal, ptr);
1718     return;
1719   }
1720 
1721   /**
1722    * Wait for GCP
1723    */
1724   ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
1725   ptr.p->masterData.waitGCP.startBackup = true;
1726 
1727   WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend();
1728   waitGCPReq->senderRef = reference();
1729   waitGCPReq->senderData = ptr.i;
1730   waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
1731   sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1732 	     WaitGCPReq::SignalLength,JBB);
1733 }
1734 
1735 void
execWAIT_GCP_REF(Signal * signal)1736 Backup::execWAIT_GCP_REF(Signal* signal)
1737 {
1738   jamEntry();
1739 
1740   CRASH_INSERTION((10006));
1741 
1742   WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr();
1743   const Uint32 ptrI = ref->senderData;
1744 
1745   BackupRecordPtr ptr LINT_SET_PTR;
1746   c_backupPool.getPtr(ptr, ptrI);
1747 
1748   ndbrequire(ptr.p->masterRef == reference());
1749   ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
1750 
1751   WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1752   req->senderRef = reference();
1753   req->senderData = ptr.i;
1754   req->requestType = WaitGCPReq::CompleteForceStart;
1755   sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1756 	     WaitGCPReq::SignalLength,JBB);
1757 }
1758 
1759 void
execWAIT_GCP_CONF(Signal * signal)1760 Backup::execWAIT_GCP_CONF(Signal* signal){
1761   jamEntry();
1762 
1763   CRASH_INSERTION((10007));
1764 
1765   WaitGCPConf * conf = (WaitGCPConf*)signal->getDataPtr();
1766   const Uint32 ptrI = conf->senderData;
1767   const Uint32 gcp = conf->gcp;
1768 
1769   BackupRecordPtr ptr LINT_SET_PTR;
1770   c_backupPool.getPtr(ptr, ptrI);
1771 
1772   ndbrequire(ptr.p->masterRef == reference());
1773   ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
1774 
1775   if(ptr.p->checkError()) {
1776     jam();
1777     masterAbort(signal, ptr);
1778     return;
1779   }//if
1780 
1781   if(ptr.p->masterData.waitGCP.startBackup) {
1782     jam();
1783     CRASH_INSERTION((10008));
1784     ptr.p->startGCP = gcp;
1785     ptr.p->masterData.sendCounter= 0;
1786     ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ;
1787     nextFragment(signal, ptr);
1788     return;
1789   } else {
1790     jam();
1791     if(gcp >= ptr.p->startGCP + 3)
1792     {
1793       CRASH_INSERTION((10009));
1794       ptr.p->stopGCP = gcp;
1795       /**
1796        * Backup is complete - begin cleanup
1797        * STOP_BACKUP_REQ is sent to participants.
1798        * They then drop the local triggers
1799        */
1800       sendStopBackup(signal, ptr);
1801       return;
1802     }//if
1803 
1804     /**
1805      * Make sure that we got entire stopGCP
1806      */
1807     WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1808     req->senderRef = reference();
1809     req->senderData = ptr.i;
1810     req->requestType = WaitGCPReq::CompleteForceStart;
1811     sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1812 	       WaitGCPReq::SignalLength,JBB);
1813     return;
1814   }
1815 }
1816 
1817 /*****************************************************************************
1818  *
1819  * Master functionallity - Backup fragment
1820  *
1821  *****************************************************************************/
1822 void
nextFragment(Signal * signal,BackupRecordPtr ptr)1823 Backup::nextFragment(Signal* signal, BackupRecordPtr ptr)
1824 {
1825   jam();
1826 
1827   BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtrSend();
1828   req->backupPtr = ptr.i;
1829   req->backupId = ptr.p->backupId;
1830 
1831   NodeBitmask nodes = ptr.p->nodes;
1832   Uint32 idleNodes = nodes.count();
1833   Uint32 saveIdleNodes = idleNodes;
1834   ndbrequire(idleNodes > 0);
1835 
1836   TablePtr tabPtr;
1837   ptr.p->tables.first(tabPtr);
1838   for(; tabPtr.i != RNIL && idleNodes > 0; ptr.p->tables.next(tabPtr)) {
1839     jam();
1840     FragmentPtr fragPtr;
1841     Array<Fragment> & frags = tabPtr.p->fragments;
1842     const Uint32 fragCount = frags.getSize();
1843 
1844     for(Uint32 i = 0; i<fragCount && idleNodes > 0; i++) {
1845       jam();
1846       tabPtr.p->fragments.getPtr(fragPtr, i);
1847       const Uint32 nodeId = fragPtr.p->node;
1848       if(fragPtr.p->scanning != 0) {
1849         jam();
1850 	ndbrequire(nodes.get(nodeId));
1851 	nodes.clear(nodeId);
1852 	idleNodes--;
1853       } else if(fragPtr.p->scanned == 0 && nodes.get(nodeId)){
1854 	jam();
1855 	fragPtr.p->scanning = 1;
1856 	nodes.clear(nodeId);
1857 	idleNodes--;
1858 
1859 	req->tableId = tabPtr.p->tableId;
1860 	req->fragmentNo = i;
1861 	req->count = 0;
1862 
1863 	ptr.p->masterData.sendCounter++;
1864 	const BlockReference ref = numberToRef(BACKUP, nodeId);
1865 	sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal,
1866 		   BackupFragmentReq::SignalLength, JBB);
1867       }//if
1868     }//for
1869   }//for
1870 
1871   if(idleNodes != saveIdleNodes){
1872     jam();
1873     return;
1874   }//if
1875 
1876   /**
1877    * Finished with all tables
1878    */
1879   {
1880     ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
1881     ptr.p->masterData.waitGCP.startBackup = false;
1882 
1883     WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1884     req->senderRef = reference();
1885     req->senderData = ptr.i;
1886     req->requestType = WaitGCPReq::CompleteForceStart;
1887     sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1888 	       WaitGCPReq::SignalLength, JBB);
1889   }
1890 }
1891 
1892 void
execBACKUP_FRAGMENT_CONF(Signal * signal)1893 Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
1894 {
1895   jamEntry();
1896 
1897   CRASH_INSERTION((10010));
1898 
1899   BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtr();
1900   const Uint32 ptrI = conf->backupPtr;
1901   //const Uint32 backupId = conf->backupId;
1902   const Uint32 tableId = conf->tableId;
1903   const Uint32 fragmentNo = conf->fragmentNo;
1904   const Uint32 nodeId = refToNode(signal->senderBlockRef());
1905   const Uint64 noOfBytes =
1906     conf->noOfBytesLow + (((Uint64)conf->noOfBytesHigh) << 32);
1907   const Uint64 noOfRecords =
1908     conf->noOfRecordsLow + (((Uint64)conf->noOfRecordsHigh) << 32);
1909 
1910   BackupRecordPtr ptr LINT_SET_PTR;
1911   c_backupPool.getPtr(ptr, ptrI);
1912 
1913   ptr.p->noOfBytes += noOfBytes;
1914   ptr.p->noOfRecords += noOfRecords;
1915   ptr.p->masterData.sendCounter--;
1916 
1917   TablePtr tabPtr;
1918   ndbrequire(findTable(ptr, tabPtr, tableId));
1919 
1920   tabPtr.p->noOfRecords += noOfRecords;
1921 
1922   FragmentPtr fragPtr;
1923   tabPtr.p->fragments.getPtr(fragPtr, fragmentNo);
1924 
1925   fragPtr.p->noOfRecords = noOfRecords;
1926 
1927   ndbrequire(fragPtr.p->scanned == 0);
1928   ndbrequire(fragPtr.p->scanning == 1);
1929   ndbrequire(fragPtr.p->node == nodeId);
1930 
1931   fragPtr.p->scanned = 1;
1932   fragPtr.p->scanning = 0;
1933 
1934   if (ERROR_INSERTED(10028))
1935   {
1936     ptr.p->errorCode = 328;
1937   }
1938 
1939   if(ptr.p->checkError())
1940   {
1941     if(ptr.p->masterData.sendCounter.done())
1942     {
1943       jam();
1944       masterAbort(signal, ptr);
1945       return;
1946     }//if
1947   }
1948   else
1949   {
1950     NodeBitmask nodes = ptr.p->nodes;
1951     nodes.clear(getOwnNodeId());
1952     if (!nodes.isclear())
1953     {
1954       BackupFragmentCompleteRep *rep =
1955         (BackupFragmentCompleteRep*)signal->getDataPtrSend();
1956       rep->backupId = ptr.p->backupId;
1957       rep->backupPtr = ptr.i;
1958       rep->tableId = tableId;
1959       rep->fragmentNo = fragmentNo;
1960       rep->noOfTableRowsLow = (Uint32)(tabPtr.p->noOfRecords & 0xFFFFFFFF);
1961       rep->noOfTableRowsHigh = (Uint32)(tabPtr.p->noOfRecords >> 32);
1962       rep->noOfFragmentRowsLow = (Uint32)(noOfRecords & 0xFFFFFFFF);
1963       rep->noOfFragmentRowsHigh = (Uint32)(noOfRecords >> 32);
1964       NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1965       sendSignal(rg, GSN_BACKUP_FRAGMENT_COMPLETE_REP, signal,
1966                  BackupFragmentCompleteRep::SignalLength, JBB);
1967     }
1968     nextFragment(signal, ptr);
1969   }
1970 }
1971 
1972 void
execBACKUP_FRAGMENT_REF(Signal * signal)1973 Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
1974 {
1975   jamEntry();
1976 
1977   CRASH_INSERTION((10011));
1978 
1979   BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
1980   const Uint32 ptrI = ref->backupPtr;
1981   //const Uint32 backupId = ref->backupId;
1982   const Uint32 nodeId = ref->nodeId;
1983 
1984   BackupRecordPtr ptr LINT_SET_PTR;
1985   c_backupPool.getPtr(ptr, ptrI);
1986 
1987   TablePtr tabPtr;
1988   ptr.p->tables.first(tabPtr);
1989   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
1990     jam();
1991     FragmentPtr fragPtr;
1992     Array<Fragment> & frags = tabPtr.p->fragments;
1993     const Uint32 fragCount = frags.getSize();
1994 
1995     for(Uint32 i = 0; i<fragCount; i++) {
1996       jam();
1997       tabPtr.p->fragments.getPtr(fragPtr, i);
1998         if(fragPtr.p->scanning != 0 && nodeId == fragPtr.p->node)
1999       {
2000         jam();
2001 	ndbrequire(fragPtr.p->scanned == 0);
2002 	fragPtr.p->scanned = 1;
2003 	fragPtr.p->scanning = 0;
2004 	goto done;
2005       }
2006     }
2007   }
2008   goto err;
2009 
2010 done:
2011   ptr.p->masterData.sendCounter--;
2012   ptr.p->setErrorCode(ref->errorCode);
2013 
2014   if(ptr.p->masterData.sendCounter.done())
2015   {
2016     jam();
2017     masterAbort(signal, ptr);
2018     return;
2019   }//if
2020 
2021 err:
2022   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2023   ord->backupId = ptr.p->backupId;
2024   ord->backupPtr = ptr.i;
2025   ord->requestType = AbortBackupOrd::LogBufferFull;
2026   ord->senderData= ptr.i;
2027   execABORT_BACKUP_ORD(signal);
2028 }
2029 
2030 void
execBACKUP_FRAGMENT_COMPLETE_REP(Signal * signal)2031 Backup::execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal)
2032 {
2033   jamEntry();
2034   BackupFragmentCompleteRep * rep =
2035     (BackupFragmentCompleteRep*)signal->getDataPtr();
2036 
2037   BackupRecordPtr ptr LINT_SET_PTR;
2038   c_backupPool.getPtr(ptr, rep->backupPtr);
2039 
2040   TablePtr tabPtr;
2041   ndbrequire(findTable(ptr, tabPtr, rep->tableId));
2042 
2043   tabPtr.p->noOfRecords =
2044     rep->noOfTableRowsLow + (((Uint64)rep->noOfTableRowsHigh) << 32);
2045 
2046   FragmentPtr fragPtr;
2047   tabPtr.p->fragments.getPtr(fragPtr, rep->fragmentNo);
2048 
2049   fragPtr.p->noOfRecords =
2050     rep->noOfFragmentRowsLow + (((Uint64)rep->noOfFragmentRowsHigh) << 32);
2051 }
2052 
2053 /*****************************************************************************
2054  *
2055  * Slave functionallity - Drop triggers
2056  *
2057  *****************************************************************************/
2058 
2059 void
sendDropTrig(Signal * signal,BackupRecordPtr ptr)2060 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr)
2061 {
2062   TablePtr tabPtr;
2063   ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
2064 
2065   if (ptr.p->slaveData.dropTrig.tableId == RNIL) {
2066     jam();
2067     if(ptr.p->tables.count())
2068       ptr.p->tables.first(tabPtr);
2069     else
2070     {
2071       // Early abort, go to close files
2072       jam();
2073       closeFiles(signal, ptr);
2074       return;
2075     }
2076   } else {
2077     jam();
2078     ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.dropTrig.tableId));
2079     ptr.p->tables.next(tabPtr);
2080   }//if
2081   if (tabPtr.i != RNIL) {
2082     jam();
2083     sendDropTrig(signal, ptr, tabPtr);
2084   } else {
2085     /**
2086      * Insert footers
2087      */
2088     //if backup error, we needn't insert footers
2089     if(ptr.p->checkError())
2090     {
2091       jam();
2092       closeFiles(signal, ptr);
2093       ptr.p->errorCode = 0;
2094       return;
2095     }
2096 
2097     {
2098       BackupFilePtr filePtr LINT_SET_PTR;
2099       ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
2100       Uint32 * dst;
2101       LINT_INIT(dst);
2102       ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
2103       * dst = 0;
2104       filePtr.p->operation.dataBuffer.updateWritePtr(1);
2105     }
2106 
2107     {
2108       BackupFilePtr filePtr LINT_SET_PTR;
2109       ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2110 
2111       const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
2112 
2113       Uint32 * dst;
2114       LINT_INIT(dst);
2115       ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
2116 
2117       BackupFormat::CtlFile::GCPEntry * gcp =
2118 	(BackupFormat::CtlFile::GCPEntry*)dst;
2119 
2120       gcp->SectionType   = htonl(BackupFormat::GCP_ENTRY);
2121       gcp->SectionLength = htonl(gcpSz);
2122       gcp->StartGCP      = htonl(ptr.p->startGCP);
2123       gcp->StopGCP       = htonl(ptr.p->stopGCP - 1);
2124       filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
2125 
2126       {
2127         TablePtr tabPtr;
2128         if (ptr.p->tables.first(tabPtr))
2129 	{
2130 	  jam();
2131 	  signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
2132 	  signal->theData[1] = ptr.i;
2133 	  signal->theData[2] = tabPtr.i;
2134 	  signal->theData[3] = 0;
2135 	  sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
2136 	}
2137 	else
2138 	{
2139 	  jam();
2140 	  closeFiles(signal, ptr);
2141 	}
2142       }
2143     }
2144   }
2145 }
2146 
2147 void
sendDropTrig(Signal * signal,BackupRecordPtr ptr,TablePtr tabPtr)2148 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
2149 {
2150   jam();
2151   DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend();
2152 
2153   ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
2154   ptr.p->slaveData.trigSendCounter = 0;
2155   req->setConnectionPtr(ptr.i);
2156   req->setUserRef(reference()); // Sending to myself
2157   req->setRequestType(DropTrigReq::RT_USER);
2158   req->setIndexId(RNIL);
2159   req->setTriggerInfo(0);       // not used on DROP
2160   req->setTriggerType(TriggerType::SUBSCRIPTION);
2161   req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
2162 
2163   ptr.p->slaveData.dropTrig.tableId = tabPtr.p->tableId;
2164   req->setTableId(tabPtr.p->tableId);
2165 
2166   for (int i = 0; i < 3; i++) {
2167     Uint32 id = tabPtr.p->triggerIds[i];
2168     req->setTriggerId(id);
2169     req->setTriggerEvent(triggerEventValues[i]);
2170     sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
2171 	       signal, DropTrigReq::SignalLength, JBB);
2172     ptr.p->slaveData.trigSendCounter ++;
2173   }
2174 }
2175 
2176 void
execDROP_TRIG_REF(Signal * signal)2177 Backup::execDROP_TRIG_REF(Signal* signal)
2178 {
2179   jamEntry();
2180 
2181   DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
2182   const Uint32 ptrI = ref->getConnectionPtr();
2183 
2184   BackupRecordPtr ptr LINT_SET_PTR;
2185   c_backupPool.getPtr(ptr, ptrI);
2186 
2187   if(ref->getConf()->getTriggerId() != ~(Uint32) 0)
2188   {
2189     ndbout << "ERROR DROPPING TRIGGER: " << ref->getConf()->getTriggerId();
2190     ndbout << " Err: " << (Uint32)ref->getErrorCode() << endl << endl;
2191   }
2192 
2193   dropTrigReply(signal, ptr);
2194 }
2195 
2196 void
execDROP_TRIG_CONF(Signal * signal)2197 Backup::execDROP_TRIG_CONF(Signal* signal)
2198 {
2199   jamEntry();
2200 
2201   DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
2202   const Uint32 ptrI = conf->getConnectionPtr();
2203 
2204   BackupRecordPtr ptr LINT_SET_PTR;
2205   c_backupPool.getPtr(ptr, ptrI);
2206 
2207   dropTrigReply(signal, ptr);
2208 }
2209 
2210 void
dropTrigReply(Signal * signal,BackupRecordPtr ptr)2211 Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr)
2212 {
2213   CRASH_INSERTION((10012));
2214 
2215   ndbrequire(ptr.p->slaveData.gsn == GSN_DROP_TRIG_REQ);
2216   ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
2217 
2218   // move from .masterData to .slaveData
2219   ptr.p->slaveData.trigSendCounter--;
2220   if(ptr.p->slaveData.trigSendCounter.done() == false){
2221     jam();
2222     return;
2223   }//if
2224 
2225   sendDropTrig(signal, ptr); // recursive next
2226 }
2227 
2228 /*****************************************************************************
2229  *
2230  * Master functionallity - Stop backup
2231  *
2232  *****************************************************************************/
2233 void
execSTOP_BACKUP_REF(Signal * signal)2234 Backup::execSTOP_BACKUP_REF(Signal* signal)
2235 {
2236   jamEntry();
2237 
2238   StopBackupRef* ref = (StopBackupRef*)signal->getDataPtr();
2239   const Uint32 ptrI = ref->backupPtr;
2240   //const Uint32 backupId = ref->backupId;
2241   const Uint32 nodeId = ref->nodeId;
2242 
2243   BackupRecordPtr ptr LINT_SET_PTR;
2244   c_backupPool.getPtr(ptr, ptrI);
2245 
2246   ptr.p->setErrorCode(ref->errorCode);
2247   stopBackupReply(signal, ptr, nodeId);
2248 }
2249 
2250 void
sendStopBackup(Signal * signal,BackupRecordPtr ptr)2251 Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr)
2252 {
2253   jam();
2254 
2255   StopBackupReq* stop = (StopBackupReq*)signal->getDataPtrSend();
2256   stop->backupPtr = ptr.i;
2257   stop->backupId = ptr.p->backupId;
2258   stop->startGCP = ptr.p->startGCP;
2259   stop->stopGCP = ptr.p->stopGCP;
2260 
2261   ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
2262   ptr.p->masterData.sendCounter = ptr.p->nodes;
2263   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
2264   sendSignal(rg, GSN_STOP_BACKUP_REQ, signal,
2265 	     StopBackupReq::SignalLength, JBB);
2266 }
2267 
2268 void
execSTOP_BACKUP_CONF(Signal * signal)2269 Backup::execSTOP_BACKUP_CONF(Signal* signal)
2270 {
2271   jamEntry();
2272 
2273   StopBackupConf* conf = (StopBackupConf*)signal->getDataPtr();
2274   const Uint32 ptrI = conf->backupPtr;
2275   //const Uint32 backupId = conf->backupId;
2276   const Uint32 nodeId = refToNode(signal->senderBlockRef());
2277 
2278   BackupRecordPtr ptr LINT_SET_PTR;
2279   c_backupPool.getPtr(ptr, ptrI);
2280 
2281   ptr.p->noOfLogBytes += conf->noOfLogBytes;
2282   ptr.p->noOfLogRecords += conf->noOfLogRecords;
2283 
2284   stopBackupReply(signal, ptr, nodeId);
2285 }
2286 
2287 void
stopBackupReply(Signal * signal,BackupRecordPtr ptr,Uint32 nodeId)2288 Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
2289 {
2290   CRASH_INSERTION((10013));
2291 
2292   if (!haveAllSignals(ptr, GSN_STOP_BACKUP_REQ, nodeId)) {
2293     jam();
2294     return;
2295   }
2296 
2297   sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete);
2298 
2299   if(!ptr.p->checkError())
2300   {
2301     if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
2302     {
2303       BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
2304       rep->backupId = ptr.p->backupId;
2305       rep->senderData = ptr.p->clientData;
2306       rep->startGCP = ptr.p->startGCP;
2307       rep->stopGCP = ptr.p->stopGCP;
2308       rep->noOfBytesLow = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
2309       rep->noOfRecordsLow = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
2310       rep->noOfBytesHigh = (Uint32)(ptr.p->noOfBytes >> 32);
2311       rep->noOfRecordsHigh = (Uint32)(ptr.p->noOfRecords >> 32);
2312       rep->noOfLogBytes = ptr.p->noOfLogBytes;
2313       rep->noOfLogRecords = ptr.p->noOfLogRecords;
2314       rep->nodes = ptr.p->nodes;
2315       sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
2316 		 BackupCompleteRep::SignalLength, JBB);
2317     }
2318 
2319     signal->theData[0] = NDB_LE_BackupCompleted;
2320     signal->theData[1] = ptr.p->clientRef;
2321     signal->theData[2] = ptr.p->backupId;
2322     signal->theData[3] = ptr.p->startGCP;
2323     signal->theData[4] = ptr.p->stopGCP;
2324     signal->theData[5] = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
2325     signal->theData[6] = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
2326     signal->theData[7] = ptr.p->noOfLogBytes;
2327     signal->theData[8] = ptr.p->noOfLogRecords;
2328     ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9);
2329     signal->theData[9+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfBytes >> 32);
2330     signal->theData[10+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfRecords >> 32);
2331     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 11+NdbNodeBitmask::Size, JBB);
2332   }
2333   else
2334   {
2335     masterAbort(signal, ptr);
2336   }
2337 }
2338 
2339 /*****************************************************************************
2340  *
2341  * Master functionallity - Abort backup
2342  *
2343  *****************************************************************************/
2344 void
masterAbort(Signal * signal,BackupRecordPtr ptr)2345 Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
2346 {
2347   jam();
2348 #ifdef DEBUG_ABORT
2349   ndbout_c("************ masterAbort");
2350 #endif
2351 
2352   ndbassert(ptr.p->masterRef == reference());
2353 
2354   if(ptr.p->masterData.errorCode != 0)
2355   {
2356     jam();
2357     return;
2358   }
2359 
2360   if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
2361   {
2362     BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
2363     rep->backupId = ptr.p->backupId;
2364     rep->senderData = ptr.p->clientData;
2365     rep->reason = ptr.p->errorCode;
2366     sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
2367 	       BackupAbortRep::SignalLength, JBB);
2368   }
2369   signal->theData[0] = NDB_LE_BackupAborted;
2370   signal->theData[1] = ptr.p->clientRef;
2371   signal->theData[2] = ptr.p->backupId;
2372   signal->theData[3] = ptr.p->errorCode;
2373   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
2374 
2375   ndbrequire(ptr.p->errorCode);
2376   ptr.p->masterData.errorCode = ptr.p->errorCode;
2377 
2378   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2379   ord->backupId = ptr.p->backupId;
2380   ord->backupPtr = ptr.i;
2381   ord->senderData= ptr.i;
2382   NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
2383 
2384   switch(ptr.p->masterData.gsn){
2385   case GSN_DEFINE_BACKUP_REQ:
2386     ord->requestType = AbortBackupOrd::BackupFailure;
2387     sendSignal(rg, GSN_ABORT_BACKUP_ORD, signal,
2388 	       AbortBackupOrd::SignalLength, JBB);
2389     return;
2390   case GSN_CREATE_TRIG_REQ:
2391   case GSN_START_BACKUP_REQ:
2392   case GSN_ALTER_TRIG_REQ:
2393   case GSN_WAIT_GCP_REQ:
2394   case GSN_BACKUP_FRAGMENT_REQ:
2395     jam();
2396     ptr.p->stopGCP= ptr.p->startGCP + 1;
2397     sendStopBackup(signal, ptr); // dropping due to error
2398     return;
2399   case GSN_UTIL_SEQUENCE_REQ:
2400   case GSN_UTIL_LOCK_REQ:
2401     ndbrequire(false);
2402     return;
2403   case GSN_DROP_TRIG_REQ:
2404   case GSN_STOP_BACKUP_REQ:
2405     return;
2406   }
2407 }
2408 
2409 void
abort_scan(Signal * signal,BackupRecordPtr ptr)2410 Backup::abort_scan(Signal * signal, BackupRecordPtr ptr)
2411 {
2412   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2413   ord->backupId = ptr.p->backupId;
2414   ord->backupPtr = ptr.i;
2415   ord->senderData= ptr.i;
2416   ord->requestType = AbortBackupOrd::AbortScan;
2417 
2418   TablePtr tabPtr;
2419   ptr.p->tables.first(tabPtr);
2420   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
2421     jam();
2422     FragmentPtr fragPtr;
2423     Array<Fragment> & frags = tabPtr.p->fragments;
2424     const Uint32 fragCount = frags.getSize();
2425 
2426     for(Uint32 i = 0; i<fragCount; i++) {
2427       jam();
2428       tabPtr.p->fragments.getPtr(fragPtr, i);
2429       const Uint32 nodeId = fragPtr.p->node;
2430       if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) {
2431         jam();
2432 
2433 	const BlockReference ref = numberToRef(BACKUP, nodeId);
2434 	sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal,
2435 		   AbortBackupOrd::SignalLength, JBB);
2436 
2437       }
2438     }
2439   }
2440 }
2441 
2442 /*****************************************************************************
2443  *
2444  * Slave functionallity: Define Backup
2445  *
2446  *****************************************************************************/
2447 void
defineBackupRef(Signal * signal,BackupRecordPtr ptr,Uint32 errCode)2448 Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode)
2449 {
2450   jam();
2451   ptr.p->setErrorCode(errCode);
2452   if(ptr.p->is_lcp())
2453   {
2454     jam();
2455      if (ptr.p->ctlFilePtr == RNIL) {
2456        ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
2457        ndbrequire(ptr.p->errorCode != 0);
2458        DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
2459        ref->backupId = ptr.p->backupId;
2460        ref->backupPtr = ptr.i;
2461        ref->errorCode = ptr.p->errorCode;
2462        ref->nodeId = getOwnNodeId();
2463        sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
2464                   DefineBackupRef::SignalLength, JBB);
2465        return;
2466      }
2467 
2468     BackupFilePtr filePtr LINT_SET_PTR;
2469     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2470     if (filePtr.p->m_flags & BackupFile::BF_LCP_META)
2471     {
2472       jam();
2473       ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD));
2474       filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
2475       if (filePtr.p->m_flags & BackupFile::BF_OPEN)
2476       {
2477 	closeFile(signal, ptr, filePtr);
2478 	return;
2479       }
2480     }
2481 
2482     ndbrequire(filePtr.p->m_flags == 0);
2483 
2484     TablePtr tabPtr;
2485     FragmentPtr fragPtr;
2486 
2487     ndbrequire(ptr.p->tables.first(tabPtr));
2488     tabPtr.p->fragments.getPtr(fragPtr, 0);
2489 
2490     LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtrSend();
2491     ref->senderData = ptr.p->clientData;
2492     ref->senderRef = reference();
2493     ref->tableId = tabPtr.p->tableId;
2494     ref->fragmentId = fragPtr.p->fragmentId;
2495     ref->errorCode = errCode;
2496     sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_REF,
2497 	       signal, LcpPrepareRef::SignalLength, JBB);
2498     return;
2499   }
2500 
2501   ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
2502   ndbrequire(ptr.p->errorCode != 0);
2503 
2504   DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
2505   ref->backupId = ptr.p->backupId;
2506   ref->backupPtr = ptr.i;
2507   ref->errorCode = ptr.p->errorCode;
2508   ref->nodeId = getOwnNodeId();
2509   sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
2510 	     DefineBackupRef::SignalLength, JBB);
2511 }
2512 
2513 void
execDEFINE_BACKUP_REQ(Signal * signal)2514 Backup::execDEFINE_BACKUP_REQ(Signal* signal)
2515 {
2516   jamEntry();
2517 
2518   DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr();
2519 
2520   BackupRecordPtr ptr LINT_SET_PTR;
2521   const Uint32 ptrI = req->backupPtr;
2522   const Uint32 backupId = req->backupId;
2523   const BlockReference senderRef = req->senderRef;
2524 
2525   if(senderRef == reference()){
2526     /**
2527      * Signal sent from myself -> record already seized
2528      */
2529     jam();
2530     c_backupPool.getPtr(ptr, ptrI);
2531   } else { // from other node
2532     jam();
2533 #ifdef DEBUG_ABORT
2534     dumpUsedResources();
2535 #endif
2536     if(!c_backups.seizeId(ptr, ptrI)) {
2537       jam();
2538       ndbrequire(false); // If master has succeeded slave should succed
2539     }//if
2540   }//if
2541 
2542   CRASH_INSERTION((10014));
2543 
2544   ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ;
2545   ptr.p->slaveState.forceState(INITIAL);
2546   ptr.p->slaveState.setState(DEFINING);
2547   ptr.p->slaveData.dropTrig.tableId = RNIL;
2548   ptr.p->errorCode = 0;
2549   ptr.p->clientRef = req->clientRef;
2550   ptr.p->clientData = req->clientData;
2551   if(senderRef == reference())
2552     ptr.p->flags = req->flags;
2553   else
2554     ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
2555 						 * as non master should never
2556 						 * reply
2557 						 */
2558   ptr.p->masterRef = senderRef;
2559   ptr.p->nodes = req->nodes;
2560   ptr.p->backupId = backupId;
2561   ptr.p->backupKey[0] = req->backupKey[0];
2562   ptr.p->backupKey[1] = req->backupKey[1];
2563   ptr.p->backupDataLen = req->backupDataLen;
2564   ptr.p->masterData.errorCode = 0;
2565   ptr.p->noOfBytes = 0;
2566   ptr.p->noOfRecords = 0;
2567   ptr.p->noOfLogBytes = 0;
2568   ptr.p->noOfLogRecords = 0;
2569   ptr.p->currGCP = 0;
2570   ptr.p->startGCP = 0;
2571   ptr.p->stopGCP = 0;
2572 
2573   /**
2574    * Allocate files
2575    */
2576   BackupFilePtr files[3];
2577   Uint32 noOfPages[] = {
2578     NO_OF_PAGES_META_FILE,
2579     2,   // 32k
2580     0    // 3M
2581   };
2582   const Uint32 maxInsert[] = {
2583     MAX_WORDS_META_FILE,
2584     4096,    // 16k
2585     16*3000, // Max 16 tuples
2586   };
2587   Uint32 minWrite[] = {
2588     8192,
2589     8192,
2590     32768
2591   };
2592   Uint32 maxWrite[] = {
2593     8192,
2594     8192,
2595     32768
2596   };
2597 
2598   minWrite[1] = c_defaults.m_minWriteSize;
2599   maxWrite[1] = c_defaults.m_maxWriteSize;
2600   noOfPages[1] = (c_defaults.m_logBufferSize + sizeof(Page32) - 1) /
2601     sizeof(Page32);
2602   minWrite[2] = c_defaults.m_minWriteSize;
2603   maxWrite[2] = c_defaults.m_maxWriteSize;
2604   noOfPages[2] = (c_defaults.m_dataBufferSize + sizeof(Page32) - 1) /
2605     sizeof(Page32);
2606 
2607   if (ptr.p->is_lcp())
2608   {
2609     noOfPages[2] = (c_defaults.m_lcp_buffer_size + sizeof(Page32) - 1) /
2610       sizeof(Page32);
2611   }
2612 
2613   ptr.p->ctlFilePtr = ptr.p->logFilePtr = ptr.p->dataFilePtr = RNIL;
2614 
2615   for(Uint32 i = 0; i<3; i++) {
2616     jam();
2617     if(ptr.p->is_lcp() && i != 2)
2618     {
2619       files[i].i = RNIL;
2620       continue;
2621     }
2622     if(!ptr.p->files.seize(files[i])) {
2623       jam();
2624       defineBackupRef(signal, ptr,
2625 		      DefineBackupRef::FailedToAllocateFileRecord);
2626       return;
2627     }//if
2628 
2629     files[i].p->tableId = RNIL;
2630     files[i].p->backupPtr = ptr.i;
2631     files[i].p->filePointer = RNIL;
2632     files[i].p->m_flags = 0;
2633     files[i].p->errorCode = 0;
2634 
2635     if(ERROR_INSERTED(10035) || files[i].p->pages.seize(noOfPages[i]) == false)
2636     {
2637       jam();
2638       DEBUG_OUT("Failed to seize " << noOfPages[i] << " pages");
2639       defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateBuffers);
2640       return;
2641     }//if
2642     Page32Ptr pagePtr;
2643     files[i].p->pages.getPtr(pagePtr, 0);
2644 
2645     const char * msg = files[i].p->
2646       operation.dataBuffer.setup((Uint32*)pagePtr.p,
2647 				 noOfPages[i] * (sizeof(Page32) >> 2),
2648 				 128,
2649 				 minWrite[i] >> 2,
2650 				 maxWrite[i] >> 2,
2651 				 maxInsert[i]);
2652     if(msg != 0) {
2653       jam();
2654       defineBackupRef(signal, ptr, DefineBackupRef::FailedToSetupFsBuffers);
2655       return;
2656     }//if
2657 
2658     switch(i){
2659     case 0:
2660       files[i].p->fileType = BackupFormat::CTL_FILE;
2661       ptr.p->ctlFilePtr = files[i].i;
2662       break;
2663     case 1:
2664       files[i].p->fileType = BackupFormat::LOG_FILE;
2665       ptr.p->logFilePtr = files[i].i;
2666       break;
2667     case 2:
2668       files[i].p->fileType = BackupFormat::DATA_FILE;
2669       ptr.p->dataFilePtr = files[i].i;
2670     }
2671   }//for
2672 
2673   if (!verifyNodesAlive(ptr, ptr.p->nodes)) {
2674     jam();
2675     defineBackupRef(signal, ptr, DefineBackupRef::Undefined);
2676     return;
2677   }//if
2678   if (ERROR_INSERTED(10027)) {
2679     jam();
2680     defineBackupRef(signal, ptr, 327);
2681     return;
2682   }//if
2683 
2684   if(ptr.p->backupDataLen == 0) {
2685     jam();
2686     backupAllData(signal, ptr);
2687     return;
2688   }//if
2689 
2690   if(ptr.p->is_lcp())
2691   {
2692     jam();
2693     getFragmentInfoDone(signal, ptr);
2694     return;
2695   }
2696 
2697   /**
2698    * Not implemented
2699    */
2700   ndbrequire(0);
2701 }
2702 
2703 void
backupAllData(Signal * signal,BackupRecordPtr ptr)2704 Backup::backupAllData(Signal* signal, BackupRecordPtr ptr)
2705 {
2706   /**
2707    * Get all tables from dict
2708    */
2709   ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend();
2710   req->senderRef = reference();
2711   req->senderData = ptr.i;
2712   req->requestData = 0;
2713   sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal,
2714 	     ListTablesReq::SignalLength, JBB);
2715 }
2716 
2717 void
execLIST_TABLES_CONF(Signal * signal)2718 Backup::execLIST_TABLES_CONF(Signal* signal)
2719 {
2720   jamEntry();
2721 
2722   ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr();
2723 
2724   BackupRecordPtr ptr LINT_SET_PTR;
2725   c_backupPool.getPtr(ptr, conf->senderData);
2726 
2727   const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
2728   for(unsigned int i = 0; i<len; i++) {
2729     jam();
2730     Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
2731     Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
2732     Uint32 state= ListTablesConf::getTableState(conf->tableData[i]);
2733 
2734     if (! (DictTabInfo::isTable(tableType) ||
2735 	   DictTabInfo::isIndex(tableType) ||
2736 	   DictTabInfo::isFilegroup(tableType) ||
2737 	   DictTabInfo::isFile(tableType)))
2738     {
2739       jam();
2740       continue;
2741     }
2742 
2743     if (state != DictTabInfo::StateOnline)
2744     {
2745       jam();
2746       continue;
2747     }
2748 
2749     TablePtr tabPtr;
2750     ptr.p->tables.seize(tabPtr);
2751     if(tabPtr.i == RNIL) {
2752       jam();
2753       defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateTables);
2754       return;
2755     }//if
2756     tabPtr.p->tableId = tableId;
2757     tabPtr.p->tableType = tableType;
2758   }//for
2759 
2760   if(len == ListTablesConf::DataLength) {
2761     jam();
2762     /**
2763      * Not finished...
2764      */
2765     return;
2766   }//if
2767 
2768   /**
2769    * All tables fetched
2770    */
2771   openFiles(signal, ptr);
2772 }
2773 
2774 void
openFiles(Signal * signal,BackupRecordPtr ptr)2775 Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
2776 {
2777   jam();
2778 
2779   BackupFilePtr filePtr LINT_SET_PTR;
2780 
2781   FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
2782   req->userReference = reference();
2783   req->fileFlags =
2784     FsOpenReq::OM_WRITEONLY |
2785     FsOpenReq::OM_TRUNCATE |
2786     FsOpenReq::OM_CREATE |
2787     FsOpenReq::OM_APPEND |
2788     FsOpenReq::OM_AUTOSYNC;
2789   FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
2790   req->auto_sync_size = c_defaults.m_disk_synch_size;
2791   /**
2792    * Ctl file
2793    */
2794   c_backupFilePool.getPtr(filePtr, ptr.p->ctlFilePtr);
2795   filePtr.p->m_flags |= BackupFile::BF_OPENING;
2796 
2797   req->userPointer = filePtr.i;
2798   FsOpenReq::setVersion(req->fileNumber, 2);
2799   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
2800   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2801   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2802   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2803 
2804   /**
2805    * Log file
2806    */
2807   c_backupFilePool.getPtr(filePtr, ptr.p->logFilePtr);
2808   filePtr.p->m_flags |= BackupFile::BF_OPENING;
2809 
2810   req->userPointer = filePtr.i;
2811   FsOpenReq::setVersion(req->fileNumber, 2);
2812   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_LOG);
2813   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2814   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2815   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2816 
2817   /**
2818    * Data file
2819    */
2820   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
2821   filePtr.p->m_flags |= BackupFile::BF_OPENING;
2822 
2823   if (c_defaults.m_o_direct)
2824     req->fileFlags |= FsOpenReq::OM_DIRECT;
2825   req->userPointer = filePtr.i;
2826   FsOpenReq::setVersion(req->fileNumber, 2);
2827   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
2828   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2829   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2830   FsOpenReq::v2_setCount(req->fileNumber, 0);
2831   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2832 }
2833 
2834 void
execFSOPENREF(Signal * signal)2835 Backup::execFSOPENREF(Signal* signal)
2836 {
2837   jamEntry();
2838 
2839   FsRef * ref = (FsRef *)signal->getDataPtr();
2840 
2841   const Uint32 userPtr = ref->userPointer;
2842 
2843   BackupFilePtr filePtr LINT_SET_PTR;
2844   c_backupFilePool.getPtr(filePtr, userPtr);
2845 
2846   BackupRecordPtr ptr LINT_SET_PTR;
2847   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
2848   ptr.p->setErrorCode(ref->errorCode);
2849   openFilesReply(signal, ptr, filePtr);
2850 }
2851 
2852 void
execFSOPENCONF(Signal * signal)2853 Backup::execFSOPENCONF(Signal* signal)
2854 {
2855   jamEntry();
2856 
2857   FsConf * conf = (FsConf *)signal->getDataPtr();
2858 
2859   const Uint32 userPtr = conf->userPointer;
2860   const Uint32 filePointer = conf->filePointer;
2861 
2862   BackupFilePtr filePtr LINT_SET_PTR;
2863   c_backupFilePool.getPtr(filePtr, userPtr);
2864   filePtr.p->filePointer = filePointer;
2865 
2866   BackupRecordPtr ptr LINT_SET_PTR;
2867   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
2868 
2869   ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPEN));
2870   filePtr.p->m_flags |= BackupFile::BF_OPEN;
2871   openFilesReply(signal, ptr, filePtr);
2872 }
2873 
2874 void
openFilesReply(Signal * signal,BackupRecordPtr ptr,BackupFilePtr filePtr)2875 Backup::openFilesReply(Signal* signal,
2876 		       BackupRecordPtr ptr, BackupFilePtr filePtr)
2877 {
2878   jam();
2879 
2880   /**
2881    * Mark files as "opened"
2882    */
2883   ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPENING);
2884   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_OPENING;
2885   filePtr.p->m_flags |= BackupFile::BF_OPEN;
2886   /**
2887    * Check if all files have recived open_reply
2888    */
2889   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
2890   {
2891     jam();
2892     if(filePtr.p->m_flags & BackupFile::BF_OPENING) {
2893       jam();
2894       return;
2895     }//if
2896   }//for
2897 
2898   /**
2899    * Did open succeed for all files
2900    */
2901   if(ptr.p->checkError()) {
2902     jam();
2903     defineBackupRef(signal, ptr);
2904     return;
2905   }//if
2906 
2907   if(!ptr.p->is_lcp())
2908   {
2909     /**
2910      * Insert file headers
2911      */
2912     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2913     if(!insertFileHeader(BackupFormat::CTL_FILE, ptr.p, filePtr.p)) {
2914       jam();
2915       defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2916       return;
2917     }//if
2918 
2919     ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
2920     if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
2921       jam();
2922       defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2923       return;
2924     }//if
2925 
2926     ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
2927     if(!insertFileHeader(BackupFormat::DATA_FILE, ptr.p, filePtr.p)) {
2928       jam();
2929       defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2930       return;
2931     }//if
2932   }
2933   else
2934   {
2935     ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
2936     if(!insertFileHeader(BackupFormat::LCP_FILE, ptr.p, filePtr.p)) {
2937       jam();
2938       defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2939       return;
2940     }//if
2941 
2942     ptr.p->ctlFilePtr = ptr.p->dataFilePtr;
2943   }
2944 
2945   /**
2946    * Start CTL file thread
2947    */
2948   if (!ptr.p->is_lcp())
2949   {
2950     jam();
2951     ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2952     filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
2953 
2954     signal->theData[0] = BackupContinueB::START_FILE_THREAD;
2955     signal->theData[1] = filePtr.i;
2956     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
2957   }
2958   else
2959   {
2960     jam();
2961     filePtr.p->m_flags |= BackupFile::BF_LCP_META;
2962   }
2963 
2964   /**
2965    * Insert table list in ctl file
2966    */
2967   FsBuffer & buf = filePtr.p->operation.dataBuffer;
2968 
2969   const Uint32 sz =
2970     (sizeof(BackupFormat::CtlFile::TableList) >> 2) +
2971     ptr.p->tables.count() - 1;
2972 
2973   Uint32 * dst;
2974   ndbrequire(sz < buf.getMaxWrite());
2975   if(!buf.getWritePtr(&dst, sz)) {
2976     jam();
2977     defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertTableList);
2978     return;
2979   }//if
2980 
2981   BackupFormat::CtlFile::TableList* tl =
2982     (BackupFormat::CtlFile::TableList*)dst;
2983   tl->SectionType   = htonl(BackupFormat::TABLE_LIST);
2984   tl->SectionLength = htonl(sz);
2985 
2986   TablePtr tabPtr;
2987   Uint32 count = 0;
2988   for(ptr.p->tables.first(tabPtr);
2989       tabPtr.i != RNIL;
2990       ptr.p->tables.next(tabPtr)){
2991     jam();
2992     tl->TableIds[count] = htonl(tabPtr.p->tableId);
2993     count++;
2994   }//for
2995 
2996   buf.updateWritePtr(sz);
2997 
2998   /**
2999    * Start getting table definition data
3000    */
3001   ndbrequire(ptr.p->tables.first(tabPtr));
3002 
3003   signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
3004   signal->theData[1] = ptr.i;
3005   signal->theData[2] = tabPtr.i;
3006   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
3007   return;
3008 }
3009 
3010 bool
insertFileHeader(BackupFormat::FileType ft,BackupRecord * ptrP,BackupFile * filePtrP)3011 Backup::insertFileHeader(BackupFormat::FileType ft,
3012 			 BackupRecord * ptrP,
3013 			 BackupFile * filePtrP){
3014   FsBuffer & buf = filePtrP->operation.dataBuffer;
3015 
3016   const Uint32 sz = sizeof(BackupFormat::FileHeader) >> 2;
3017 
3018   Uint32 * dst;
3019   ndbrequire(sz < buf.getMaxWrite());
3020   if(!buf.getWritePtr(&dst, sz)) {
3021     jam();
3022     return false;
3023   }//if
3024 
3025   BackupFormat::FileHeader* header = (BackupFormat::FileHeader*)dst;
3026   ndbrequire(sizeof(header->Magic) == sizeof(BACKUP_MAGIC));
3027   memcpy(header->Magic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC));
3028   header->NdbVersion    = htonl(NDB_VERSION);
3029   header->SectionType   = htonl(BackupFormat::FILE_HEADER);
3030   header->SectionLength = htonl(sz - 3);
3031   header->FileType      = htonl(ft);
3032   header->BackupId      = htonl(ptrP->backupId);
3033   header->BackupKey_0   = htonl(ptrP->backupKey[0]);
3034   header->BackupKey_1   = htonl(ptrP->backupKey[1]);
3035   header->ByteOrder     = 0x12345678;
3036 
3037   buf.updateWritePtr(sz);
3038   return true;
3039 }
3040 
3041 void
execGET_TABINFOREF(Signal * signal)3042 Backup::execGET_TABINFOREF(Signal* signal)
3043 {
3044   GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr();
3045 
3046   const Uint32 senderData = ref->senderData;
3047   BackupRecordPtr ptr LINT_SET_PTR;
3048   c_backupPool.getPtr(ptr, senderData);
3049 
3050   BackupFilePtr filePtr LINT_SET_PTR;
3051   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
3052   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
3053 
3054   defineBackupRef(signal, ptr, ref->errorCode);
3055 }
3056 
3057 void
execGET_TABINFO_CONF(Signal * signal)3058 Backup::execGET_TABINFO_CONF(Signal* signal)
3059 {
3060   jamEntry();
3061 
3062   if(!assembleFragments(signal)) {
3063     jam();
3064     return;
3065   }//if
3066 
3067   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
3068   //const Uint32 senderRef = info->senderRef;
3069   const Uint32 len = conf->totalLen;
3070   const Uint32 senderData = conf->senderData;
3071   const Uint32 tableType = conf->tableType;
3072   const Uint32 tableId = conf->tableId;
3073 
3074   BackupRecordPtr ptr LINT_SET_PTR;
3075   c_backupPool.getPtr(ptr, senderData);
3076 
3077   SegmentedSectionPtr dictTabInfoPtr;
3078   signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
3079   ndbrequire(dictTabInfoPtr.sz == len);
3080 
3081   TablePtr tabPtr ;
3082   ndbrequire(findTable(ptr, tabPtr, tableId));
3083 
3084   BackupFilePtr filePtr LINT_SET_PTR;
3085   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
3086   FsBuffer & buf = filePtr.p->operation.dataBuffer;
3087   Uint32* dst = 0;
3088   { // Write into ctl file
3089     Uint32 dstLen = len + 3;
3090     if(!buf.getWritePtr(&dst, dstLen)) {
3091       jam();
3092       ndbrequire(false);
3093       ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
3094       releaseSections(signal);
3095       defineBackupRef(signal, ptr);
3096       return;
3097     }//if
3098     if(dst != 0) {
3099       jam();
3100 
3101       BackupFormat::CtlFile::TableDescription * desc =
3102         (BackupFormat::CtlFile::TableDescription*)dst;
3103       desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION);
3104       desc->SectionLength = htonl(len + 3);
3105       desc->TableType = htonl(tableType);
3106       dst += 3;
3107 
3108       copy(dst, dictTabInfoPtr);
3109       buf.updateWritePtr(dstLen);
3110     }//if
3111   }
3112 
3113   releaseSections(signal);
3114 
3115   if(ptr.p->checkError()) {
3116     jam();
3117     defineBackupRef(signal, ptr);
3118     return;
3119   }//if
3120 
3121   if (!DictTabInfo::isTable(tabPtr.p->tableType))
3122   {
3123     jam();
3124 
3125     TablePtr tmp = tabPtr;
3126     ptr.p->tables.next(tabPtr);
3127     ptr.p->tables.release(tmp);
3128     goto next;
3129   }
3130 
3131   if (!parseTableDescription(signal, ptr, tabPtr, dst, len))
3132   {
3133     jam();
3134     defineBackupRef(signal, ptr);
3135     return;
3136   }
3137 
3138   if(!ptr.p->is_lcp())
3139   {
3140     jam();
3141     signal->theData[0] = tabPtr.p->tableId;
3142     signal->theData[1] = 1; // lock
3143     EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
3144   }
3145 
3146   ptr.p->tables.next(tabPtr);
3147 
3148 next:
3149   if(tabPtr.i == RNIL)
3150   {
3151     /**
3152      * Done with all tables...
3153      */
3154     jam();
3155 
3156     if(ptr.p->is_lcp())
3157     {
3158       lcp_open_file_done(signal, ptr);
3159       return;
3160     }
3161 
3162     ndbrequire(ptr.p->tables.first(tabPtr));
3163     DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
3164     req->m_connectionData = RNIL;
3165     req->m_tableRef = tabPtr.p->tableId;
3166     req->m_senderData = ptr.i;
3167     sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
3168                DihFragCountReq::SignalLength, JBB);
3169     return;
3170   }//if
3171 
3172   /**
3173    * Fetch next table...
3174    */
3175   signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
3176   signal->theData[1] = ptr.i;
3177   signal->theData[2] = tabPtr.i;
3178   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
3179   return;
3180 }
3181 
3182 bool
parseTableDescription(Signal * signal,BackupRecordPtr ptr,TablePtr tabPtr,const Uint32 * tabdescptr,Uint32 len)3183 Backup::parseTableDescription(Signal* signal,
3184 			      BackupRecordPtr ptr,
3185 			      TablePtr tabPtr,
3186 			      const Uint32 * tabdescptr,
3187 			      Uint32 len)
3188 {
3189   SimplePropertiesLinearReader it(tabdescptr, len);
3190 
3191   it.first();
3192 
3193   DictTabInfo::Table tmpTab; tmpTab.init();
3194   SimpleProperties::UnpackStatus stat;
3195   stat = SimpleProperties::unpack(it, &tmpTab,
3196 				  DictTabInfo::TableMapping,
3197 				  DictTabInfo::TableMappingSize,
3198 				  true, true);
3199   ndbrequire(stat == SimpleProperties::Break);
3200 
3201   bool lcp = ptr.p->is_lcp();
3202 
3203   ndbrequire(tabPtr.p->tableId == tmpTab.TableId);
3204   ndbrequire(lcp || (tabPtr.p->tableType == tmpTab.TableType));
3205 
3206   /**
3207    * LCP should not save disk attributes but only mem attributes
3208    */
3209 
3210   /**
3211    * Initialize table object
3212    */
3213   tabPtr.p->noOfRecords = 0;
3214   tabPtr.p->schemaVersion = tmpTab.TableVersion;
3215   tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
3216   tabPtr.p->noOfNull = 0;
3217   tabPtr.p->noOfVariable = 0; // Computed while iterating over attribs
3218   tabPtr.p->sz_FixedAttributes = 0; // Computed while iterating over attribs
3219   tabPtr.p->triggerIds[0] = ILLEGAL_TRIGGER_ID;
3220   tabPtr.p->triggerIds[1] = ILLEGAL_TRIGGER_ID;
3221   tabPtr.p->triggerIds[2] = ILLEGAL_TRIGGER_ID;
3222   tabPtr.p->triggerAllocated[0] = false;
3223   tabPtr.p->triggerAllocated[1] = false;
3224   tabPtr.p->triggerAllocated[2] = false;
3225 
3226   Uint32 disk = 0;
3227   const Uint32 count = tabPtr.p->noOfAttributes;
3228   for(Uint32 i = 0; i<count; i++) {
3229     jam();
3230     DictTabInfo::Attribute tmp; tmp.init();
3231     stat = SimpleProperties::unpack(it, &tmp,
3232 				    DictTabInfo::AttributeMapping,
3233 				    DictTabInfo::AttributeMappingSize,
3234 				    true, true);
3235 
3236     ndbrequire(stat == SimpleProperties::Break);
3237     it.next(); // Move Past EndOfAttribute
3238 
3239     const Uint32 arr = tmp.AttributeArraySize;
3240     const Uint32 sz = 1 << tmp.AttributeSize;
3241     const Uint32 sz32 = (sz * arr + 31) >> 5;
3242 
3243     if(lcp && tmp.AttributeStorageType == NDB_STORAGETYPE_DISK)
3244     {
3245       disk++;
3246       continue;
3247     }
3248 
3249     AttributePtr attrPtr;
3250     if(!tabPtr.p->attributes.seize(attrPtr))
3251     {
3252       jam();
3253       ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
3254       return false;
3255     }
3256 
3257     attrPtr.p->data.m_flags = 0;
3258     attrPtr.p->data.attrId = tmp.AttributeId;
3259 
3260     attrPtr.p->data.m_flags |=
3261       (tmp.AttributeNullableFlag ? Attribute::COL_NULLABLE : 0);
3262     attrPtr.p->data.m_flags |= (tmp.AttributeArrayType == NDB_ARRAYTYPE_FIXED)?
3263       Attribute::COL_FIXED : 0;
3264     attrPtr.p->data.sz32 = sz32;
3265 
3266     /**
3267      * 1) Fixed non-nullable
3268      * 2) Other
3269      */
3270     if(attrPtr.p->data.m_flags & Attribute::COL_FIXED &&
3271        !(attrPtr.p->data.m_flags & Attribute::COL_NULLABLE)) {
3272       jam();
3273       attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3274       tabPtr.p->sz_FixedAttributes += sz32;
3275     } else {
3276       attrPtr.p->data.offset = ~0;
3277       tabPtr.p->noOfVariable++;
3278     }
3279   }//for
3280 
3281 
3282   if(lcp)
3283   {
3284     if (disk)
3285     {
3286       /**
3287        * Remove all disk attributes
3288        */
3289       tabPtr.p->noOfAttributes -= disk;
3290 
3291       {
3292 	AttributePtr attrPtr;
3293 	ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3294 
3295 	Uint32 sz32 = 2;
3296 	attrPtr.p->data.attrId = AttributeHeader::DISK_REF;
3297 	attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3298 	attrPtr.p->data.sz32 = 2;
3299 
3300 	attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3301 	tabPtr.p->sz_FixedAttributes += sz32;
3302 	tabPtr.p->noOfAttributes ++;
3303       }
3304     }
3305 
3306     {
3307       AttributePtr attrPtr;
3308       ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3309 
3310       Uint32 sz32 = 2;
3311       attrPtr.p->data.attrId = AttributeHeader::ROWID;
3312       attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3313       attrPtr.p->data.sz32 = 2;
3314 
3315       attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3316       tabPtr.p->sz_FixedAttributes += sz32;
3317       tabPtr.p->noOfAttributes ++;
3318     }
3319 
3320     if (tmpTab.RowGCIFlag)
3321     {
3322       AttributePtr attrPtr;
3323       ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3324 
3325       Uint32 sz32 = 2;
3326       attrPtr.p->data.attrId = AttributeHeader::ROW_GCI;
3327       attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3328       attrPtr.p->data.sz32 = 2;
3329 
3330       attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3331       tabPtr.p->sz_FixedAttributes += sz32;
3332       tabPtr.p->noOfAttributes ++;
3333     }
3334   }
3335   return true;
3336 }
3337 
3338 void
execDI_FCOUNTCONF(Signal * signal)3339 Backup::execDI_FCOUNTCONF(Signal* signal)
3340 {
3341   jamEntry();
3342   DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
3343   const Uint32 userPtr = conf->m_connectionData;
3344   const Uint32 fragCount = conf->m_fragmentCount;
3345   const Uint32 tableId = conf->m_tableRef;
3346   const Uint32 senderData = conf->m_senderData;
3347 
3348   ndbrequire(userPtr == RNIL && signal->length() == 5);
3349 
3350   BackupRecordPtr ptr LINT_SET_PTR;
3351   c_backupPool.getPtr(ptr, senderData);
3352 
3353   TablePtr tabPtr;
3354   ndbrequire(findTable(ptr, tabPtr, tableId));
3355 
3356   ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
3357   for(Uint32 i = 0; i<fragCount; i++) {
3358     jam();
3359     FragmentPtr fragPtr;
3360     tabPtr.p->fragments.getPtr(fragPtr, i);
3361     fragPtr.p->scanned = 0;
3362     fragPtr.p->scanning = 0;
3363     fragPtr.p->tableId = tableId;
3364     fragPtr.p->fragmentId = i;
3365     fragPtr.p->node = 0;
3366   }//for
3367 
3368   /**
3369    * Next table
3370    */
3371   if(ptr.p->tables.next(tabPtr)) {
3372     jam();
3373     DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
3374     req->m_connectionData = RNIL;
3375     req->m_tableRef = tabPtr.p->tableId;
3376     req->m_senderData = ptr.i;
3377     sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
3378                DihFragCountReq::SignalLength, JBB);
3379     return;
3380   }//if
3381 
3382   ptr.p->tables.first(tabPtr);
3383   getFragmentInfo(signal, ptr, tabPtr, 0);
3384 }
3385 
3386 void
getFragmentInfo(Signal * signal,BackupRecordPtr ptr,TablePtr tabPtr,Uint32 fragNo)3387 Backup::getFragmentInfo(Signal* signal,
3388 			BackupRecordPtr ptr, TablePtr tabPtr, Uint32 fragNo)
3389 {
3390   jam();
3391 
3392   for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
3393     jam();
3394     const Uint32 fragCount = tabPtr.p->fragments.getSize();
3395     for(; fragNo < fragCount; fragNo ++) {
3396       jam();
3397       FragmentPtr fragPtr;
3398       tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3399 
3400       if(fragPtr.p->scanned == 0 && fragPtr.p->scanning == 0) {
3401 	jam();
3402 	signal->theData[0] = RNIL;
3403 	signal->theData[1] = ptr.i;
3404 	signal->theData[2] = tabPtr.p->tableId;
3405 	signal->theData[3] = fragNo;
3406 	sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
3407 	return;
3408       }//if
3409     }//for
3410     fragNo = 0;
3411   }//for
3412 
3413   getFragmentInfoDone(signal, ptr);
3414 }
3415 
3416 void
execDIGETPRIMCONF(Signal * signal)3417 Backup::execDIGETPRIMCONF(Signal* signal)
3418 {
3419   jamEntry();
3420 
3421   const Uint32 userPtr = signal->theData[0];
3422   const Uint32 senderData = signal->theData[1];
3423   const Uint32 nodeCount = signal->theData[6];
3424   const Uint32 tableId = signal->theData[7];
3425   const Uint32 fragNo = signal->theData[8];
3426 
3427   ndbrequire(userPtr == RNIL && signal->length() == 9);
3428   ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
3429 
3430   BackupRecordPtr ptr LINT_SET_PTR;
3431   c_backupPool.getPtr(ptr, senderData);
3432 
3433   TablePtr tabPtr;
3434   ndbrequire(findTable(ptr, tabPtr, tableId));
3435 
3436   FragmentPtr fragPtr;
3437   tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3438 
3439   fragPtr.p->node = signal->theData[2];
3440 
3441   getFragmentInfo(signal, ptr, tabPtr, fragNo + 1);
3442 }
3443 
3444 void
getFragmentInfoDone(Signal * signal,BackupRecordPtr ptr)3445 Backup::getFragmentInfoDone(Signal* signal, BackupRecordPtr ptr)
3446 {
3447   ptr.p->m_gsn = GSN_DEFINE_BACKUP_CONF;
3448   ptr.p->slaveState.setState(DEFINED);
3449   DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtr();
3450   conf->backupPtr = ptr.i;
3451   conf->backupId = ptr.p->backupId;
3452   sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_CONF, signal,
3453 	     DefineBackupConf::SignalLength, JBB);
3454 }
3455 
3456 
3457 /*****************************************************************************
3458  *
3459  * Slave functionallity: Start backup
3460  *
3461  *****************************************************************************/
3462 void
execSTART_BACKUP_REQ(Signal * signal)3463 Backup::execSTART_BACKUP_REQ(Signal* signal)
3464 {
3465   jamEntry();
3466 
3467   CRASH_INSERTION((10015));
3468 
3469   StartBackupReq* req = (StartBackupReq*)signal->getDataPtr();
3470   const Uint32 ptrI = req->backupPtr;
3471 
3472   BackupRecordPtr ptr LINT_SET_PTR;
3473   c_backupPool.getPtr(ptr, ptrI);
3474 
3475   ptr.p->slaveState.setState(STARTED);
3476   ptr.p->m_gsn = GSN_START_BACKUP_REQ;
3477 
3478   /**
3479    * Start file threads...
3480    */
3481   BackupFilePtr filePtr;
3482   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
3483   {
3484     jam();
3485     if(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD))
3486     {
3487       jam();
3488       filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
3489       signal->theData[0] = BackupContinueB::START_FILE_THREAD;
3490       signal->theData[1] = filePtr.i;
3491       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
3492     }//if
3493   }//for
3494 
3495   /**
3496    * Tell DBTUP to create triggers
3497    */
3498   TablePtr tabPtr;
3499   ndbrequire(ptr.p->tables.first(tabPtr));
3500   sendCreateTrig(signal, ptr, tabPtr);
3501 }
3502 
3503 /*****************************************************************************
3504  *
3505  * Slave functionallity: Backup fragment
3506  *
3507  *****************************************************************************/
3508 void
execBACKUP_FRAGMENT_REQ(Signal * signal)3509 Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
3510 {
3511   jamEntry();
3512   BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtr();
3513 
3514   CRASH_INSERTION((10016));
3515 
3516   const Uint32 ptrI = req->backupPtr;
3517   //const Uint32 backupId = req->backupId;
3518   const Uint32 tableId = req->tableId;
3519   const Uint32 fragNo = req->fragmentNo;
3520   const Uint32 count = req->count;
3521 
3522   /**
3523    * Get backup record
3524    */
3525   BackupRecordPtr ptr LINT_SET_PTR;
3526   c_backupPool.getPtr(ptr, ptrI);
3527 
3528   ptr.p->slaveState.setState(SCANNING);
3529   ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REQ;
3530 
3531   /**
3532    * Get file
3533    */
3534   BackupFilePtr filePtr LINT_SET_PTR;
3535   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
3536 
3537   ndbrequire(filePtr.p->backupPtr == ptrI);
3538   ndbrequire(filePtr.p->m_flags ==
3539 	     (BackupFile::BF_OPEN | BackupFile::BF_FILE_THREAD));
3540 
3541   /**
3542    * Get table
3543    */
3544   TablePtr tabPtr;
3545   ndbrequire(findTable(ptr, tabPtr, tableId));
3546 
3547   /**
3548    * Get fragment
3549    */
3550   FragmentPtr fragPtr;
3551   tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3552 
3553   ndbrequire(fragPtr.p->scanned == 0);
3554   ndbrequire(fragPtr.p->scanning == 0 ||
3555 	     refToNode(ptr.p->masterRef) == getOwnNodeId());
3556 
3557   /**
3558    * Init operation
3559    */
3560   if(filePtr.p->tableId != tableId) {
3561     jam();
3562     filePtr.p->operation.init(tabPtr);
3563     filePtr.p->tableId = tableId;
3564   }//if
3565 
3566   /**
3567    * Check for space in buffer
3568    */
3569   if(!filePtr.p->operation.newFragment(tableId, fragPtr.p->fragmentId)) {
3570     jam();
3571     req->count = count + 1;
3572     sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
3573 			signal->length());
3574     ptr.p->slaveState.setState(STARTED);
3575     return;
3576   }//if
3577 
3578   /**
3579    * Mark things as "in use"
3580    */
3581   fragPtr.p->scanning = 1;
3582   filePtr.p->fragmentNo = fragPtr.p->fragmentId;
3583 
3584   /**
3585    * Start scan
3586    */
3587   {
3588     filePtr.p->m_flags |= BackupFile::BF_SCAN_THREAD;
3589 
3590     Table & table = * tabPtr.p;
3591     ScanFragReq * req = (ScanFragReq *)signal->getDataPtrSend();
3592     const Uint32 parallelism = 16;
3593     const Uint32 attrLen = 5 + table.noOfAttributes;
3594 
3595     req->senderData = filePtr.i;
3596     req->resultRef = reference();
3597     req->schemaVersion = table.schemaVersion;
3598     req->fragmentNoKeyLen = fragPtr.p->fragmentId;
3599     req->requestInfo = 0;
3600     req->savePointId = 0;
3601     req->tableId = table.tableId;
3602     ScanFragReq::setReadCommittedFlag(req->requestInfo, 1);
3603     ScanFragReq::setLockMode(req->requestInfo, 0);
3604     ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
3605     ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
3606     ScanFragReq::setAttrLen(req->requestInfo,attrLen);
3607     ScanFragReq::setTupScanFlag(req->requestInfo, 1);
3608     if (ptr.p->is_lcp())
3609     {
3610       ScanFragReq::setScanPrio(req->requestInfo, 1);
3611       ScanFragReq::setNoDiskFlag(req->requestInfo, 1);
3612       ScanFragReq::setLcpScanFlag(req->requestInfo, 1);
3613     }
3614     req->transId1 = 0;
3615     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
3616     req->clientOpPtr= filePtr.i;
3617     req->batch_size_rows= parallelism;
3618     req->batch_size_bytes= 0;
3619     sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal,
3620                ScanFragReq::SignalLength, JBB);
3621 
3622     signal->theData[0] = filePtr.i;
3623     signal->theData[1] = 0;
3624     signal->theData[2] = (BACKUP << 20) + (getOwnNodeId() << 8);
3625 
3626     // Return all
3627     signal->theData[3] = table.noOfAttributes;
3628     signal->theData[4] = 0;
3629     signal->theData[5] = 0;
3630     signal->theData[6] = 0;
3631     signal->theData[7] = 0;
3632 
3633     Uint32 dataPos = 8;
3634     Ptr<Attribute> attrPtr;
3635     table.attributes.first(attrPtr);
3636     for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
3637     {
3638       jam();
3639 
3640       /**
3641        * LCP should not save disk attributes
3642        */
3643       ndbrequire(! (ptr.p->is_lcp() &&
3644 		    attrPtr.p->data.m_flags & Attribute::COL_DISK));
3645 
3646       AttributeHeader::init(&signal->theData[dataPos],
3647 			    attrPtr.p->data.attrId, 0);
3648       dataPos++;
3649       if(dataPos == 25) {
3650         jam();
3651 	sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, 25, JBB);
3652 	dataPos = 3;
3653       }//if
3654     }//for
3655     if(dataPos != 3) {
3656       jam();
3657       sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, dataPos, JBB);
3658     }//if
3659   }
3660 }
3661 
3662 void
execSCAN_HBREP(Signal * signal)3663 Backup::execSCAN_HBREP(Signal* signal)
3664 {
3665   jamEntry();
3666 }
3667 
3668 void
execTRANSID_AI(Signal * signal)3669 Backup::execTRANSID_AI(Signal* signal)
3670 {
3671   jamEntry();
3672 
3673   const Uint32 filePtrI = signal->theData[0];
3674   //const Uint32 transId1 = signal->theData[1];
3675   //const Uint32 transId2 = signal->theData[2];
3676   const Uint32 dataLen  = signal->length() - 3;
3677 
3678   BackupFilePtr filePtr LINT_SET_PTR;
3679   c_backupFilePool.getPtr(filePtr, filePtrI);
3680 
3681   OperationRecord & op = filePtr.p->operation;
3682 
3683   TablePtr tabPtr LINT_SET_PTR;
3684   c_tablePool.getPtr(tabPtr, op.tablePtr);
3685 
3686   Table & table = * tabPtr.p;
3687 
3688   /**
3689    * Unpack data
3690    */
3691   op.attrSzTotal += dataLen;
3692 
3693   Uint32 srcSz = dataLen;
3694   Uint32 usedSz = 0;
3695   const Uint32 * src = &signal->theData[3];
3696 
3697   Ptr<Attribute> attrPtr;
3698   table.attributes.first(attrPtr);
3699   Uint32 columnNo = 0;
3700 
3701   while (usedSz < srcSz)
3702   {
3703     jam();
3704 
3705     /**
3706      * Finished with one attribute now find next
3707      */
3708     const AttributeHeader attrHead(* src);
3709     const Uint32 attrId = attrHead.getAttributeId();
3710     const bool null = attrHead.isNULL();
3711     const Attribute::Data attr = attrPtr.p->data;
3712     ndbrequire(attrId == attr.attrId);
3713 
3714     usedSz += attrHead.getHeaderSize();
3715     src    += attrHead.getHeaderSize();
3716 
3717     if (null) {
3718       jam();
3719       ndbrequire(attr.m_flags & Attribute::COL_NULLABLE);
3720       op.nullVariable();
3721     } else {
3722       Uint32* dst;
3723       Uint32 dstSz = attrHead.getDataSize();
3724       if (attr.m_flags & Attribute::COL_FIXED &&
3725          ! (attr.m_flags & Attribute::COL_NULLABLE)) {
3726         jam();
3727         dst = op.newAttrib(attr.offset, dstSz);
3728         ndbrequire(dstSz == attr.sz32);
3729       } else {
3730         dst = op.newVariable(columnNo, attrHead.getByteSize());
3731         ndbrequire(dstSz <= attr.sz32);
3732       }
3733 
3734       memcpy(dst, src, (dstSz << 2));
3735       src    += dstSz;
3736       usedSz += dstSz;
3737     }
3738     table.attributes.next(attrPtr);
3739     columnNo++;
3740   }
3741 
3742   ndbrequire(usedSz == srcSz);
3743   ndbrequire(op.finished());
3744   op.newRecord(op.dst);
3745 }
3746 
3747 void
init(const TablePtr & ptr)3748 Backup::OperationRecord::init(const TablePtr & ptr)
3749 {
3750 
3751   tablePtr = ptr.i;
3752   noOfAttributes = ptr.p->noOfAttributes;
3753 
3754   sz_Bitmask = (ptr.p->noOfNull + 31) >> 5;
3755   sz_FixedAttribs = ptr.p->sz_FixedAttributes;
3756 
3757   if(ptr.p->noOfVariable == 0) {
3758     jam();
3759     maxRecordSize = 1 + sz_Bitmask + sz_FixedAttribs;
3760   } else {
3761     jam();
3762     maxRecordSize =
3763       1 + sz_Bitmask + 2048 /* Max tuple size */ + 2 * ptr.p->noOfVariable;
3764   }//if
3765 }
3766 
3767 bool
newFragment(Uint32 tableId,Uint32 fragNo)3768 Backup::OperationRecord::newFragment(Uint32 tableId, Uint32 fragNo)
3769 {
3770   Uint32 * tmp;
3771   const Uint32 headSz = (sizeof(BackupFormat::DataFile::FragmentHeader) >> 2);
3772   const Uint32 sz = headSz + 16 * maxRecordSize;
3773 
3774   ndbrequire(sz < dataBuffer.getMaxWrite());
3775   if(dataBuffer.getWritePtr(&tmp, sz)) {
3776     jam();
3777     BackupFormat::DataFile::FragmentHeader * head =
3778       (BackupFormat::DataFile::FragmentHeader*)tmp;
3779 
3780     head->SectionType   = htonl(BackupFormat::FRAGMENT_HEADER);
3781     head->SectionLength = htonl(headSz);
3782     head->TableId       = htonl(tableId);
3783     head->FragmentNo    = htonl(fragNo);
3784     head->ChecksumType  = htonl(0);
3785 
3786     opNoDone = opNoConf = opLen = 0;
3787     newRecord(tmp + headSz);
3788     scanStart = tmp;
3789     scanStop  = (tmp + headSz);
3790 
3791     noOfRecords = 0;
3792     noOfBytes = 0;
3793     return true;
3794   }//if
3795   return false;
3796 }
3797 
3798 bool
fragComplete(Uint32 tableId,Uint32 fragNo,bool fill_record)3799 Backup::OperationRecord::fragComplete(Uint32 tableId, Uint32 fragNo, bool fill_record)
3800 {
3801   Uint32 * tmp;
3802   const Uint32 footSz = sizeof(BackupFormat::DataFile::FragmentFooter) >> 2;
3803   Uint32 sz = footSz + 1;
3804 
3805   if (fill_record)
3806   {
3807     Uint32 * new_tmp;
3808     if (!dataBuffer.getWritePtr(&tmp, sz))
3809       return false;
3810     new_tmp = tmp + sz;
3811 
3812     if ((UintPtr)new_tmp & (sizeof(Page32)-1))
3813     {
3814       /* padding is needed to get full write */
3815       new_tmp += 2 /* to fit empty header minimum 2 words*/;
3816       new_tmp = (Uint32 *)(((UintPtr)new_tmp + sizeof(Page32)-1) &
3817                             ~(UintPtr)(sizeof(Page32)-1));
3818       /* new write sz */
3819       sz = new_tmp - tmp;
3820     }
3821   }
3822 
3823   if(dataBuffer.getWritePtr(&tmp, sz)) {
3824     jam();
3825     * tmp = 0; // Finish record stream
3826     tmp++;
3827     BackupFormat::DataFile::FragmentFooter * foot =
3828       (BackupFormat::DataFile::FragmentFooter*)tmp;
3829     foot->SectionType   = htonl(BackupFormat::FRAGMENT_FOOTER);
3830     foot->SectionLength = htonl(footSz);
3831     foot->TableId       = htonl(tableId);
3832     foot->FragmentNo    = htonl(fragNo);
3833     foot->NoOfRecords   = htonl(noOfRecords);
3834     foot->Checksum      = htonl(0);
3835 
3836     if (sz != footSz + 1)
3837     {
3838       tmp += footSz;
3839       memset(tmp, 0, (sz - footSz - 1) * 4);
3840       *tmp = htonl(BackupFormat::EMPTY_ENTRY);
3841       tmp++;
3842       *tmp = htonl(sz - footSz - 1);
3843     }
3844 
3845     dataBuffer.updateWritePtr(sz);
3846     return true;
3847   }//if
3848   return false;
3849 }
3850 
3851 bool
newScan()3852 Backup::OperationRecord::newScan()
3853 {
3854   Uint32 * tmp;
3855   ndbrequire(16 * maxRecordSize < dataBuffer.getMaxWrite());
3856   if(dataBuffer.getWritePtr(&tmp, 16 * maxRecordSize)) {
3857     jam();
3858     opNoDone = opNoConf = opLen = 0;
3859     newRecord(tmp);
3860     scanStart = tmp;
3861     scanStop = tmp;
3862     return true;
3863   }//if
3864   return false;
3865 }
3866 
3867 bool
closeScan()3868 Backup::OperationRecord::closeScan()
3869 {
3870   opNoDone = opNoConf = opLen = 0;
3871   return true;
3872 }
3873 
3874 bool
scanConf(Uint32 noOfOps,Uint32 total_len)3875 Backup::OperationRecord::scanConf(Uint32 noOfOps, Uint32 total_len)
3876 {
3877   const Uint32 done = opNoDone-opNoConf;
3878 
3879   ndbrequire(noOfOps == done);
3880   ndbrequire(opLen == total_len);
3881   opNoConf = opNoDone;
3882 
3883   const Uint32 len = (scanStop - scanStart);
3884   ndbrequire(len < dataBuffer.getMaxWrite());
3885   dataBuffer.updateWritePtr(len);
3886   noOfBytes += (len << 2);
3887   return true;
3888 }
3889 
3890 void
execSCAN_FRAGREF(Signal * signal)3891 Backup::execSCAN_FRAGREF(Signal* signal)
3892 {
3893   jamEntry();
3894 
3895   ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr();
3896 
3897   const Uint32 filePtrI = ref->senderData;
3898   BackupFilePtr filePtr LINT_SET_PTR;
3899   c_backupFilePool.getPtr(filePtr, filePtrI);
3900 
3901   filePtr.p->errorCode = ref->errorCode;
3902   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3903 
3904   backupFragmentRef(signal, filePtr);
3905 }
3906 
3907 void
execSCAN_FRAGCONF(Signal * signal)3908 Backup::execSCAN_FRAGCONF(Signal* signal)
3909 {
3910   jamEntry();
3911 
3912   CRASH_INSERTION((10017));
3913 
3914   ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr();
3915 
3916   const Uint32 filePtrI = conf->senderData;
3917   BackupFilePtr filePtr LINT_SET_PTR;
3918   c_backupFilePool.getPtr(filePtr, filePtrI);
3919 
3920   OperationRecord & op = filePtr.p->operation;
3921 
3922   op.scanConf(conf->completedOps, conf->total_len);
3923   const Uint32 completed = conf->fragmentCompleted;
3924   if(completed != 2) {
3925     jam();
3926 
3927     checkScan(signal, filePtr);
3928     return;
3929   }//if
3930 
3931   fragmentCompleted(signal, filePtr);
3932 }
3933 
3934 void
fragmentCompleted(Signal * signal,BackupFilePtr filePtr)3935 Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
3936 {
3937   jam();
3938 
3939   if(filePtr.p->errorCode != 0)
3940   {
3941     jam();
3942     filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3943     backupFragmentRef(signal, filePtr); // Scan completed
3944     return;
3945   }//if
3946 
3947   BackupRecordPtr ptr LINT_SET_PTR;
3948   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
3949 
3950   OperationRecord & op = filePtr.p->operation;
3951   if(!op.fragComplete(filePtr.p->tableId, filePtr.p->fragmentNo,
3952                       c_defaults.m_o_direct))
3953   {
3954     jam();
3955     signal->theData[0] = BackupContinueB::BUFFER_FULL_FRAG_COMPLETE;
3956     signal->theData[1] = filePtr.i;
3957     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
3958     return;
3959   }//if
3960 
3961   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3962 
3963   if (ptr.p->is_lcp())
3964   {
3965     ptr.p->slaveState.setState(STOPPING);
3966     filePtr.p->operation.dataBuffer.eof();
3967   }
3968   else
3969   {
3970     BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
3971     conf->backupId = ptr.p->backupId;
3972     conf->backupPtr = ptr.i;
3973     conf->tableId = filePtr.p->tableId;
3974     conf->fragmentNo = filePtr.p->fragmentNo;
3975     conf->noOfRecordsLow = (Uint32)(op.noOfRecords & 0xFFFFFFFF);
3976     conf->noOfRecordsHigh = (Uint32)(op.noOfRecords >> 32);
3977     conf->noOfBytesLow = (Uint32)(op.noOfBytes & 0xFFFFFFFF);
3978     conf->noOfBytesHigh = (Uint32)(op.noOfBytes >> 32);
3979     sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
3980 	       BackupFragmentConf::SignalLength, JBB);
3981 
3982     ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_CONF;
3983     ptr.p->slaveState.setState(STARTED);
3984   }
3985   return;
3986 }
3987 
3988 void
backupFragmentRef(Signal * signal,BackupFilePtr filePtr)3989 Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr)
3990 {
3991   BackupRecordPtr ptr LINT_SET_PTR;
3992   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
3993 
3994   ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF;
3995 
3996   BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtrSend();
3997   ref->backupId = ptr.p->backupId;
3998   ref->backupPtr = ptr.i;
3999   ref->nodeId = getOwnNodeId();
4000   ref->errorCode = filePtr.p->errorCode;
4001   sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal,
4002 	     BackupFragmentRef::SignalLength, JBB);
4003 }
4004 
4005 void
checkScan(Signal * signal,BackupFilePtr filePtr)4006 Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
4007 {
4008   OperationRecord & op = filePtr.p->operation;
4009 
4010   if(filePtr.p->errorCode != 0)
4011   {
4012     jam();
4013 
4014     /**
4015      * Close scan
4016      */
4017     op.closeScan();
4018     ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
4019     req->senderData = filePtr.i;
4020     req->closeFlag = 1;
4021     req->transId1 = 0;
4022     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
4023     sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4024 	       ScanFragNextReq::SignalLength, JBB);
4025     return;
4026   }//if
4027 
4028   if(op.newScan()) {
4029     jam();
4030 
4031     ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
4032     req->senderData = filePtr.i;
4033     req->closeFlag = 0;
4034     req->transId1 = 0;
4035     req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
4036     req->batch_size_rows= 16;
4037     req->batch_size_bytes= 0;
4038 
4039     if (ERROR_INSERTED(10036) &&
4040 	filePtr.p->tableId >= 2 &&
4041 	filePtr.p->operation.noOfRecords > 0)
4042     {
4043       ndbout_c("halting backup for table %d fragment: %d after %llu records",
4044 	       filePtr.p->tableId,
4045 	       filePtr.p->fragmentNo,
4046 	       filePtr.p->operation.noOfRecords);
4047       memmove(signal->theData+1, signal->theData,
4048 	      4*ScanFragNextReq::SignalLength);
4049       signal->theData[0] = BackupContinueB::ZDELAY_SCAN_NEXT;
4050       sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
4051 			  300, 1+ScanFragNextReq::SignalLength);
4052       return;
4053     }
4054     if(ERROR_INSERTED(10032))
4055       sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4056 			  100, ScanFragNextReq::SignalLength);
4057     else if(ERROR_INSERTED(10033))
4058     {
4059       SET_ERROR_INSERT_VALUE(10032);
4060       sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4061 			  10000, ScanFragNextReq::SignalLength);
4062 
4063       BackupRecordPtr ptr LINT_SET_PTR;
4064       c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4065       AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4066       ord->backupId = ptr.p->backupId;
4067       ord->backupPtr = ptr.i;
4068       ord->requestType = AbortBackupOrd::FileOrScanError;
4069       ord->senderData= ptr.i;
4070       sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
4071 		 AbortBackupOrd::SignalLength, JBB);
4072     }
4073     else
4074       sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4075 		 ScanFragNextReq::SignalLength, JBB);
4076     return;
4077   }//if
4078 
4079   signal->theData[0] = BackupContinueB::BUFFER_FULL_SCAN;
4080   signal->theData[1] = filePtr.i;
4081   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
4082 }
4083 
4084 void
execFSAPPENDREF(Signal * signal)4085 Backup::execFSAPPENDREF(Signal* signal)
4086 {
4087   jamEntry();
4088 
4089   FsRef * ref = (FsRef *)signal->getDataPtr();
4090 
4091   const Uint32 filePtrI = ref->userPointer;
4092   const Uint32 errCode = ref->errorCode;
4093 
4094   BackupFilePtr filePtr LINT_SET_PTR;
4095   c_backupFilePool.getPtr(filePtr, filePtrI);
4096 
4097   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4098   filePtr.p->errorCode = errCode;
4099 
4100   checkFile(signal, filePtr);
4101 }
4102 
4103 void
execFSAPPENDCONF(Signal * signal)4104 Backup::execFSAPPENDCONF(Signal* signal)
4105 {
4106   jamEntry();
4107 
4108   CRASH_INSERTION((10018));
4109 
4110   //FsConf * conf = (FsConf*)signal->getDataPtr();
4111   const Uint32 filePtrI = signal->theData[0]; //conf->userPointer;
4112   const Uint32 bytes = signal->theData[1]; //conf->bytes;
4113 
4114   BackupFilePtr filePtr LINT_SET_PTR;
4115   c_backupFilePool.getPtr(filePtr, filePtrI);
4116 
4117   OperationRecord & op = filePtr.p->operation;
4118 
4119   op.dataBuffer.updateReadPtr(bytes >> 2);
4120 
4121   checkFile(signal, filePtr);
4122 }
4123 
4124 /*
4125   This routine handles two problems with writing to disk during local
4126   checkpoints and backups. The first problem is that we need to limit
4127   the writing to ensure that we don't use too much CPU and disk resources
4128   for backups and checkpoints. The perfect solution to this is to use
4129   a dynamic algorithm that adapts to the environment. Until we have
4130   implemented this we can satisfy ourselves with an algorithm that
4131   uses a configurable limit.
4132 
4133   The second problem is that in Linux we can get severe problems if we
4134   write very much to the disk without synching. In the worst case we
4135   can have Gigabytes of data in the Linux page cache before we reach
4136   the limit of how much we can write. If this happens the performance
4137   will drop significantly when we reach this limit since the Linux flush
4138   daemon will spend a few minutes on writing out the page cache to disk.
4139   To avoid this we ensure that a file never have more than a certain
4140   amount of data outstanding before synch. This variable is also
4141   configurable.
4142 */
4143 bool
ready_to_write(bool ready,Uint32 sz,bool eof,BackupFile * fileP)4144 Backup::ready_to_write(bool ready, Uint32 sz, bool eof, BackupFile *fileP)
4145 {
4146 #if 0
4147   ndbout << "ready_to_write: ready = " << ready << " eof = " << eof;
4148   ndbout << " sz = " << sz << endl;
4149   ndbout << "words this period = " << m_words_written_this_period;
4150   ndbout << endl << "overflow disk write = " << m_overflow_disk_write;
4151   ndbout << endl << "Current Millisecond is = ";
4152   ndbout << NdbTick_CurrentMillisecond() << endl;
4153 #endif
4154   if ((ready || eof) &&
4155       m_words_written_this_period <= m_curr_disk_write_speed)
4156   {
4157     /*
4158       We have a buffer ready to write or we have reached end of
4159       file and thus we must write the last before closing the
4160       file.
4161       We have already check that we are allowed to write at this
4162       moment. We only worry about history of last 100 milliseconds.
4163       What happened before that is of no interest since a disk
4164       write that was issued more than 100 milliseconds should be
4165       completed by now.
4166     */
4167     int overflow;
4168     m_words_written_this_period += sz;
4169     overflow = m_words_written_this_period - m_curr_disk_write_speed;
4170     if (overflow > 0)
4171       m_overflow_disk_write = overflow;
4172 #if 0
4173     ndbout << "Will write with " << endl;
4174     ndbout << endl;
4175 #endif
4176     return true;
4177   }
4178   else
4179   {
4180 #if 0
4181     ndbout << "Will not write now" << endl << endl;
4182 #endif
4183     return false;
4184   }
4185 }
4186 
4187 void
checkFile(Signal * signal,BackupFilePtr filePtr)4188 Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
4189 {
4190 
4191 #ifdef DEBUG_ABORT
4192   //  ndbout_c("---- check file filePtr.i = %u", filePtr.i);
4193 #endif
4194 
4195   OperationRecord & op = filePtr.p->operation;
4196   Uint32 *tmp = NULL;
4197   Uint32 sz = 0;
4198   bool eof = FALSE;
4199   bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
4200 #if 0
4201   ndbout << "Ptr to data = " << hex << tmp << endl;
4202 #endif
4203   BackupRecordPtr ptr LINT_SET_PTR;
4204   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4205 
4206   if (ERROR_INSERTED(10036))
4207   {
4208     jam();
4209     filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4210     filePtr.p->errorCode = 2810;
4211     ptr.p->setErrorCode(2810);
4212 
4213     if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
4214     {
4215       jam();
4216       closeFile(signal, ptr, filePtr);
4217     }
4218     return;
4219   }
4220 
4221   if(filePtr.p->errorCode != 0)
4222   {
4223     jam();
4224     ptr.p->setErrorCode(filePtr.p->errorCode);
4225 
4226     if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
4227     {
4228       jam();
4229       closeFile(signal, ptr, filePtr);
4230     }
4231     return;
4232   }
4233 
4234   if (!ready_to_write(ready, sz, eof, filePtr.p))
4235   {
4236     jam();
4237     signal->theData[0] = BackupContinueB::BUFFER_UNDERFLOW;
4238     signal->theData[1] = filePtr.i;
4239     sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 20, 2);
4240     return;
4241   }
4242   else if (sz > 0)
4243   {
4244     jam();
4245     FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend();
4246     req->filePointer   = filePtr.p->filePointer;
4247     req->userPointer   = filePtr.i;
4248     req->userReference = reference();
4249     req->varIndex      = 0;
4250     req->offset        = tmp - c_startOfPages;
4251     req->size          = sz;
4252     req->synch_flag    = 0;
4253 
4254     sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal,
4255 	       FsAppendReq::SignalLength, JBA);
4256     return;
4257   }
4258 
4259   Uint32 flags = filePtr.p->m_flags;
4260   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4261 
4262   ndbrequire(flags & BackupFile::BF_OPEN);
4263   ndbrequire(flags & BackupFile::BF_FILE_THREAD);
4264 
4265   closeFile(signal, ptr, filePtr);
4266 }
4267 
4268 
4269 /****************************************************************************
4270  *
4271  * Slave functionallity: Perform logging
4272  *
4273  ****************************************************************************/
4274 void
execBACKUP_TRIG_REQ(Signal * signal)4275 Backup::execBACKUP_TRIG_REQ(Signal* signal)
4276 {
4277   /*
4278   TUP asks if this trigger is to be fired on this node.
4279   */
4280   TriggerPtr trigPtr LINT_SET_PTR;
4281   TablePtr tabPtr LINT_SET_PTR;
4282   FragmentPtr fragPtr;
4283   Uint32 trigger_id = signal->theData[0];
4284   Uint32 frag_id = signal->theData[1];
4285   Uint32 result;
4286 
4287   jamEntry();
4288 
4289   c_triggerPool.getPtr(trigPtr, trigger_id);
4290 
4291   c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
4292   tabPtr.p->fragments.getPtr(fragPtr, frag_id);
4293   if (fragPtr.p->node != getOwnNodeId()) {
4294 
4295     jam();
4296     result = ZFALSE;
4297   } else {
4298     jam();
4299     result = ZTRUE;
4300   }//if
4301   signal->theData[0] = result;
4302 }
4303 
4304 void
execTRIG_ATTRINFO(Signal * signal)4305 Backup::execTRIG_ATTRINFO(Signal* signal) {
4306   jamEntry();
4307 
4308   CRASH_INSERTION((10019));
4309 
4310   TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr();
4311 
4312   TriggerPtr trigPtr LINT_SET_PTR;
4313   c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
4314   ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
4315 
4316   if(trigPtr.p->errorCode != 0) {
4317     jam();
4318     return;
4319   }//if
4320 
4321   if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
4322     jam();
4323     /**
4324      * Backup is doing REDO logging and don't need before values
4325      */
4326     return;
4327   }//if
4328 
4329   BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
4330   if(logEntry == 0)
4331   {
4332     jam();
4333     Uint32 * dst;
4334     FsBuffer & buf = trigPtr.p->operation->dataBuffer;
4335     ndbrequire(trigPtr.p->maxRecordSize <= buf.getMaxWrite());
4336 
4337     if(ERROR_INSERTED(10030) ||
4338        !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize))
4339     {
4340       jam();
4341       Uint32 save[TrigAttrInfo::StaticLength];
4342       memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength);
4343       BackupRecordPtr ptr LINT_SET_PTR;
4344       c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
4345       trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull;
4346       AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4347       ord->backupId = ptr.p->backupId;
4348       ord->backupPtr = ptr.i;
4349       ord->requestType = AbortBackupOrd::LogBufferFull;
4350       ord->senderData= ptr.i;
4351       sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
4352 		 AbortBackupOrd::SignalLength, JBB);
4353 
4354       memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength);
4355       return;
4356     }//if
4357 
4358     logEntry = (BackupFormat::LogFile::LogEntry *)dst;
4359     trigPtr.p->logEntry = logEntry;
4360     logEntry->Length       = 0;
4361     logEntry->TableId      = htonl(trigPtr.p->tableId);
4362 
4363 
4364     if(trigPtr.p->event==0)
4365       logEntry->TriggerEvent= htonl(TriggerEvent::TE_INSERT);
4366     else if(trigPtr.p->event==1)
4367       logEntry->TriggerEvent= htonl(TriggerEvent::TE_UPDATE);
4368     else if(trigPtr.p->event==2)
4369       logEntry->TriggerEvent= htonl(TriggerEvent::TE_DELETE);
4370     else {
4371       ndbout << "Bad Event: " << trigPtr.p->event << endl;
4372       ndbrequire(false);
4373     }
4374   } else {
4375     ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId));
4376 //    ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event));
4377   }//if
4378 
4379   const Uint32 pos = logEntry->Length;
4380   const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
4381   memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2);
4382 
4383   logEntry->Length = pos + dataLen;
4384 }
4385 
4386 void
execFIRE_TRIG_ORD(Signal * signal)4387 Backup::execFIRE_TRIG_ORD(Signal* signal)
4388 {
4389   jamEntry();
4390   FireTrigOrd* trg = (FireTrigOrd*)signal->getDataPtr();
4391 
4392   const Uint32 gci = trg->getGCI();
4393   const Uint32 trI = trg->getTriggerId();
4394   const Uint32 fragId = trg->fragId;
4395 
4396   TriggerPtr trigPtr LINT_SET_PTR;
4397   c_triggerPool.getPtr(trigPtr, trI);
4398 
4399   ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
4400 
4401   if(trigPtr.p->errorCode != 0) {
4402     jam();
4403     return;
4404   }//if
4405 
4406   ndbrequire(trigPtr.p->logEntry != 0);
4407   Uint32 len = trigPtr.p->logEntry->Length;
4408   trigPtr.p->logEntry->FragId = htonl(fragId);
4409 
4410   BackupRecordPtr ptr LINT_SET_PTR;
4411   c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
4412   if(gci != ptr.p->currGCP)
4413   {
4414     jam();
4415     trigPtr.p->logEntry->TriggerEvent|= htonl(0x10000);
4416     trigPtr.p->logEntry->Data[len] = htonl(gci);
4417     len++;
4418     ptr.p->currGCP = gci;
4419   }
4420 
4421   len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
4422   trigPtr.p->logEntry->Length = htonl(len);
4423 
4424   ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
4425   trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
4426   trigPtr.p->logEntry = 0;
4427 
4428   trigPtr.p->operation->noOfBytes += (len + 1) << 2;
4429   trigPtr.p->operation->noOfRecords += 1;
4430 }
4431 
4432 void
sendAbortBackupOrd(Signal * signal,BackupRecordPtr ptr,Uint32 requestType)4433 Backup::sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr,
4434 			   Uint32 requestType)
4435 {
4436   jam();
4437   AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4438   ord->backupId = ptr.p->backupId;
4439   ord->backupPtr = ptr.i;
4440   ord->requestType = requestType;
4441   ord->senderData= ptr.i;
4442   NodePtr node;
4443   for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
4444     jam();
4445     const Uint32 nodeId = node.p->nodeId;
4446     if(node.p->alive && ptr.p->nodes.get(nodeId)) {
4447       jam();
4448       sendSignal(numberToRef(BACKUP, nodeId), GSN_ABORT_BACKUP_ORD, signal,
4449 		 AbortBackupOrd::SignalLength, JBB);
4450     }//if
4451   }//for
4452 }
4453 
4454 /*****************************************************************************
4455  *
4456  * Slave functionallity: Stop backup
4457  *
4458  *****************************************************************************/
4459 void
execSTOP_BACKUP_REQ(Signal * signal)4460 Backup::execSTOP_BACKUP_REQ(Signal* signal)
4461 {
4462   jamEntry();
4463   StopBackupReq * req = (StopBackupReq*)signal->getDataPtr();
4464 
4465   CRASH_INSERTION((10020));
4466 
4467   const Uint32 ptrI = req->backupPtr;
4468   //const Uint32 backupId = req->backupId;
4469   const Uint32 startGCP = req->startGCP;
4470   const Uint32 stopGCP = req->stopGCP;
4471 
4472   /**
4473    * At least one GCP must have passed
4474    */
4475   ndbrequire(stopGCP > startGCP);
4476 
4477   /**
4478    * Get backup record
4479    */
4480   BackupRecordPtr ptr LINT_SET_PTR;
4481   c_backupPool.getPtr(ptr, ptrI);
4482 
4483   ptr.p->slaveState.setState(STOPPING);
4484   ptr.p->m_gsn = GSN_STOP_BACKUP_REQ;
4485   ptr.p->startGCP= startGCP;
4486   ptr.p->stopGCP= stopGCP;
4487 
4488   /**
4489    * Destroy the triggers in local DBTUP we created
4490    */
4491   sendDropTrig(signal, ptr);
4492 }
4493 
4494 void
closeFiles(Signal * sig,BackupRecordPtr ptr)4495 Backup::closeFiles(Signal* sig, BackupRecordPtr ptr)
4496 {
4497   /**
4498    * Close all files
4499    */
4500   BackupFilePtr filePtr;
4501   int openCount = 0;
4502   for(ptr.p->files.first(filePtr); filePtr.i!=RNIL; ptr.p->files.next(filePtr))
4503   {
4504     if(! (filePtr.p->m_flags & BackupFile::BF_OPEN))
4505     {
4506       jam();
4507       continue;
4508     }
4509 
4510     jam();
4511     openCount++;
4512 
4513     if(filePtr.p->m_flags & BackupFile::BF_CLOSING)
4514     {
4515       jam();
4516       continue;
4517     }//if
4518 
4519     filePtr.p->operation.dataBuffer.eof();
4520     if(filePtr.p->m_flags & BackupFile::BF_FILE_THREAD)
4521     {
4522       jam();
4523 #ifdef DEBUG_ABORT
4524       ndbout_c("Close files fileRunning == 1, filePtr.i=%u", filePtr.i);
4525 #endif
4526     }
4527     else
4528     {
4529       jam();
4530       closeFile(sig, ptr, filePtr);
4531     }
4532   }
4533 
4534   if(openCount == 0){
4535     jam();
4536     closeFilesDone(sig, ptr);
4537   }//if
4538 }
4539 
4540 void
closeFile(Signal * signal,BackupRecordPtr ptr,BackupFilePtr filePtr)4541 Backup::closeFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr)
4542 {
4543   ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPEN);
4544   ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPENING));
4545   ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_CLOSING));
4546   filePtr.p->m_flags |= BackupFile::BF_CLOSING;
4547 
4548   FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend();
4549   req->filePointer = filePtr.p->filePointer;
4550   req->userPointer = filePtr.i;
4551   req->userReference = reference();
4552   req->fileFlag = 0;
4553 
4554   if (ptr.p->errorCode)
4555   {
4556     FsCloseReq::setRemoveFileFlag(req->fileFlag, 1);
4557   }
4558 
4559 #ifdef DEBUG_ABORT
4560   ndbout_c("***** a FSCLOSEREQ filePtr.i = %u flags: %x",
4561 	   filePtr.i, filePtr.p->m_flags);
4562 #endif
4563   sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
4564 
4565 }
4566 
4567 void
execFSCLOSEREF(Signal * signal)4568 Backup::execFSCLOSEREF(Signal* signal)
4569 {
4570   jamEntry();
4571 
4572   FsRef * ref = (FsRef*)signal->getDataPtr();
4573   const Uint32 filePtrI = ref->userPointer;
4574 
4575   BackupFilePtr filePtr LINT_SET_PTR;
4576   c_backupFilePool.getPtr(filePtr, filePtrI);
4577 
4578   BackupRecordPtr ptr LINT_SET_PTR;
4579   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4580 
4581   FsConf * conf = (FsConf*)signal->getDataPtr();
4582   conf->userPointer = filePtrI;
4583 
4584   execFSCLOSECONF(signal);
4585 }
4586 
4587 void
execFSCLOSECONF(Signal * signal)4588 Backup::execFSCLOSECONF(Signal* signal)
4589 {
4590   jamEntry();
4591 
4592   FsConf * conf = (FsConf*)signal->getDataPtr();
4593   const Uint32 filePtrI = conf->userPointer;
4594 
4595   BackupFilePtr filePtr LINT_SET_PTR;
4596   c_backupFilePool.getPtr(filePtr, filePtrI);
4597 
4598 #ifdef DEBUG_ABORT
4599   ndbout_c("***** FSCLOSECONF filePtrI = %u", filePtrI);
4600 #endif
4601 
4602   ndbrequire(filePtr.p->m_flags == (BackupFile::BF_OPEN |
4603 				    BackupFile::BF_CLOSING));
4604 
4605 
4606   filePtr.p->m_flags &= ~(Uint32)(BackupFile::BF_OPEN |BackupFile::BF_CLOSING);
4607   filePtr.p->operation.dataBuffer.reset();
4608 
4609   BackupRecordPtr ptr LINT_SET_PTR;
4610   c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4611   closeFiles(signal, ptr);
4612 }
4613 
4614 void
closeFilesDone(Signal * signal,BackupRecordPtr ptr)4615 Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr)
4616 {
4617   jam();
4618 
4619   if(ptr.p->is_lcp())
4620   {
4621     lcp_close_file_conf(signal, ptr);
4622     return;
4623   }
4624 
4625   jam();
4626 
4627   //error when do insert footer or close file
4628   if(ptr.p->checkError())
4629   {
4630     StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
4631     ref->backupPtr = ptr.i;
4632     ref->backupId = ptr.p->backupId;
4633     ref->errorCode = ptr.p->errorCode;
4634     ref->nodeId = getOwnNodeId();
4635     sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_REF, signal,
4636              StopBackupConf::SignalLength, JBB);
4637 
4638     ptr.p->m_gsn = GSN_STOP_BACKUP_REF;
4639     ptr.p->slaveState.setState(CLEANING);
4640     return;
4641   }
4642 
4643   StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend();
4644   conf->backupId = ptr.p->backupId;
4645   conf->backupPtr = ptr.i;
4646 
4647   BackupFilePtr filePtr LINT_SET_PTR;
4648   if(ptr.p->logFilePtr != RNIL)
4649   {
4650     ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
4651     conf->noOfLogBytes= filePtr.p->operation.noOfBytes;
4652     conf->noOfLogRecords= filePtr.p->operation.noOfRecords;
4653   }
4654   else
4655   {
4656     conf->noOfLogBytes= 0;
4657     conf->noOfLogRecords= 0;
4658   }
4659 
4660   sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal,
4661 	     StopBackupConf::SignalLength, JBB);
4662 
4663   ptr.p->m_gsn = GSN_STOP_BACKUP_CONF;
4664   ptr.p->slaveState.setState(CLEANING);
4665 }
4666 
4667 /*****************************************************************************
4668  *
4669  * Slave functionallity: Abort backup
4670  *
4671  *****************************************************************************/
4672 /*****************************************************************************
4673  *
4674  * Slave functionallity: Abort backup
4675  *
4676  *****************************************************************************/
4677 void
execABORT_BACKUP_ORD(Signal * signal)4678 Backup::execABORT_BACKUP_ORD(Signal* signal)
4679 {
4680   jamEntry();
4681   AbortBackupOrd* ord = (AbortBackupOrd*)signal->getDataPtr();
4682 
4683   const Uint32 backupId = ord->backupId;
4684   const AbortBackupOrd::RequestType requestType =
4685     (AbortBackupOrd::RequestType)ord->requestType;
4686   const Uint32 senderData = ord->senderData;
4687 
4688 #ifdef DEBUG_ABORT
4689   ndbout_c("******** ABORT_BACKUP_ORD ********* nodeId = %u",
4690 	   refToNode(signal->getSendersBlockRef()));
4691   ndbout_c("backupId = %u, requestType = %u, senderData = %u, ",
4692 	   backupId, requestType, senderData);
4693   dumpUsedResources();
4694 #endif
4695 
4696   BackupRecordPtr ptr LINT_SET_PTR;
4697   if(requestType == AbortBackupOrd::ClientAbort) {
4698     if (getOwnNodeId() != getMasterNodeId()) {
4699       jam();
4700       // forward to master
4701 #ifdef DEBUG_ABORT
4702       ndbout_c("---- Forward to master nodeId = %u", getMasterNodeId());
4703 #endif
4704       sendSignal(calcBackupBlockRef(getMasterNodeId()), GSN_ABORT_BACKUP_ORD,
4705 		 signal, AbortBackupOrd::SignalLength, JBB);
4706       return;
4707     }
4708     jam();
4709     for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
4710       jam();
4711       if(ptr.p->backupId == backupId && ptr.p->clientData == senderData) {
4712         jam();
4713 	break;
4714       }//if
4715     }//for
4716     if(ptr.i == RNIL) {
4717       jam();
4718       return;
4719     }//if
4720   } else {
4721     if (c_backupPool.findId(senderData)) {
4722       jam();
4723       c_backupPool.getPtr(ptr, senderData);
4724     } else {
4725       jam();
4726 #ifdef DEBUG_ABORT
4727       ndbout_c("Backup: abort request type=%u on id=%u,%u not found",
4728 	       requestType, backupId, senderData);
4729 #endif
4730       return;
4731     }
4732   }//if
4733 
4734   ptr.p->m_gsn = GSN_ABORT_BACKUP_ORD;
4735   const bool isCoordinator = (ptr.p->masterRef == reference());
4736 
4737   bool ok = false;
4738   switch(requestType){
4739 
4740     /**
4741      * Requests sent to master
4742      */
4743   case AbortBackupOrd::ClientAbort:
4744     jam();
4745     // fall through
4746   case AbortBackupOrd::LogBufferFull:
4747     jam();
4748     // fall through
4749   case AbortBackupOrd::FileOrScanError:
4750     jam();
4751     ndbrequire(isCoordinator);
4752     ptr.p->setErrorCode(requestType);
4753     if(ptr.p->masterData.gsn == GSN_BACKUP_FRAGMENT_REQ)
4754     {
4755       /**
4756        * Only scans are actively aborted
4757        */
4758       abort_scan(signal, ptr);
4759     }
4760     return;
4761 
4762     /**
4763      * Requests sent to slave
4764      */
4765   case AbortBackupOrd::AbortScan:
4766     jam();
4767     ptr.p->setErrorCode(requestType);
4768     return;
4769 
4770   case AbortBackupOrd::BackupComplete:
4771     jam();
4772     cleanup(signal, ptr);
4773     return;
4774   case AbortBackupOrd::BackupFailure:
4775   case AbortBackupOrd::BackupFailureDueToNodeFail:
4776   case AbortBackupOrd::OkToClean:
4777   case AbortBackupOrd::IncompatibleVersions:
4778 #ifndef VM_TRACE
4779   default:
4780 #endif
4781     ptr.p->setErrorCode(requestType);
4782     ok= true;
4783   }
4784   ndbrequire(ok);
4785 
4786   ptr.p->masterRef = reference();
4787   ptr.p->nodes.clear();
4788   ptr.p->nodes.set(getOwnNodeId());
4789 
4790 
4791   ptr.p->stopGCP= ptr.p->startGCP + 1;
4792   sendStopBackup(signal, ptr);
4793 }
4794 
4795 
4796 void
dumpUsedResources()4797 Backup::dumpUsedResources()
4798 {
4799   jam();
4800   BackupRecordPtr ptr;
4801 
4802   for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
4803     ndbout_c("Backup id=%u, slaveState.getState = %u, errorCode=%u",
4804 	     ptr.p->backupId,
4805 	     ptr.p->slaveState.getState(),
4806 	     ptr.p->errorCode);
4807 
4808     TablePtr tabPtr;
4809     for(ptr.p->tables.first(tabPtr);
4810 	tabPtr.i != RNIL;
4811 	ptr.p->tables.next(tabPtr)) {
4812       jam();
4813       for(Uint32 j = 0; j<3; j++) {
4814 	jam();
4815 	TriggerPtr trigPtr LINT_SET_PTR;
4816 	if(tabPtr.p->triggerAllocated[j]) {
4817 	  jam();
4818 	  c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
4819 	  ndbout_c("Allocated[%u] Triggerid = %u, event = %u",
4820 		 j,
4821 		 tabPtr.p->triggerIds[j],
4822 		 trigPtr.p->event);
4823 	}//if
4824       }//for
4825     }//for
4826 
4827     BackupFilePtr filePtr;
4828     for(ptr.p->files.first(filePtr);
4829 	filePtr.i != RNIL;
4830 	ptr.p->files.next(filePtr)) {
4831       jam();
4832       ndbout_c("filePtr.i = %u, flags: H'%x ",
4833 	       filePtr.i, filePtr.p->m_flags);
4834     }//for
4835   }
4836 }
4837 
4838 void
cleanup(Signal * signal,BackupRecordPtr ptr)4839 Backup::cleanup(Signal* signal, BackupRecordPtr ptr)
4840 {
4841 
4842   TablePtr tabPtr;
4843   for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;ptr.p->tables.next(tabPtr))
4844   {
4845     jam();
4846     tabPtr.p->attributes.release();
4847     tabPtr.p->fragments.release();
4848     for(Uint32 j = 0; j<3; j++) {
4849       jam();
4850       TriggerPtr trigPtr LINT_SET_PTR;
4851       if(tabPtr.p->triggerAllocated[j]) {
4852         jam();
4853 	c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
4854 	trigPtr.p->event = ILLEGAL_TRIGGER_ID;
4855         tabPtr.p->triggerAllocated[j] = false;
4856       }//if
4857       tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID;
4858     }//for
4859     {
4860       signal->theData[0] = tabPtr.p->tableId;
4861       signal->theData[1] = 0; // unlock
4862       EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
4863     }
4864   }//for
4865 
4866   BackupFilePtr filePtr;
4867   for(ptr.p->files.first(filePtr);filePtr.i != RNIL;ptr.p->files.next(filePtr))
4868   {
4869     jam();
4870     ndbrequire(filePtr.p->m_flags == 0);
4871     filePtr.p->pages.release();
4872   }//for
4873 
4874   ptr.p->files.release();
4875   ptr.p->tables.release();
4876   ptr.p->triggers.release();
4877   ptr.p->backupId = ~0;
4878 
4879   if(ptr.p->checkError())
4880     removeBackup(signal, ptr);
4881   else
4882     c_backups.release(ptr);
4883 }
4884 
4885 
4886 void
removeBackup(Signal * signal,BackupRecordPtr ptr)4887 Backup::removeBackup(Signal* signal, BackupRecordPtr ptr)
4888 {
4889   jam();
4890 
4891   FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
4892   req->userReference = reference();
4893   req->userPointer = ptr.i;
4894   req->directory = 1;
4895   req->ownDirectory = 1;
4896   FsOpenReq::setVersion(req->fileNumber, 2);
4897   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
4898   FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
4899   FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
4900   sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
4901 	     FsRemoveReq::SignalLength, JBA);
4902 }
4903 
4904 void
execFSREMOVEREF(Signal * signal)4905 Backup::execFSREMOVEREF(Signal* signal)
4906 {
4907   jamEntry();
4908   FsRef * ref = (FsRef*)signal->getDataPtr();
4909   const Uint32 ptrI = ref->userPointer;
4910 
4911   FsConf * conf = (FsConf*)signal->getDataPtr();
4912   conf->userPointer = ptrI;
4913   execFSREMOVECONF(signal);
4914 }
4915 
4916 void
execFSREMOVECONF(Signal * signal)4917 Backup::execFSREMOVECONF(Signal* signal){
4918   jamEntry();
4919 
4920   FsConf * conf = (FsConf*)signal->getDataPtr();
4921   const Uint32 ptrI = conf->userPointer;
4922 
4923   /**
4924    * Get backup record
4925    */
4926   BackupRecordPtr ptr LINT_SET_PTR;
4927   c_backupPool.getPtr(ptr, ptrI);
4928   c_backups.release(ptr);
4929 }
4930 
4931 /**
4932  * LCP
4933  */
4934 void
execLCP_PREPARE_REQ(Signal * signal)4935 Backup::execLCP_PREPARE_REQ(Signal* signal)
4936 {
4937   jamEntry();
4938   LcpPrepareReq req = *(LcpPrepareReq*)signal->getDataPtr();
4939 
4940   BackupRecordPtr ptr LINT_SET_PTR;
4941   c_backupPool.getPtr(ptr, req.backupPtr);
4942 
4943   ptr.p->m_gsn = GSN_LCP_PREPARE_REQ;
4944 
4945   TablePtr tabPtr;
4946   FragmentPtr fragPtr;
4947   if (!ptr.p->tables.isEmpty())
4948   {
4949     jam();
4950     ndbrequire(ptr.p->errorCode);
4951     ptr.p->tables.first(tabPtr);
4952     if (tabPtr.p->tableId == req.tableId)
4953     {
4954       jam();
4955       ndbrequire(!tabPtr.p->fragments.empty());
4956       tabPtr.p->fragments.getPtr(fragPtr, 0);
4957       fragPtr.p->fragmentId = req.fragmentId;
4958       defineBackupRef(signal, ptr, ptr.p->errorCode);
4959       return;
4960     }
4961     else
4962     {
4963       jam();
4964       tabPtr.p->attributes.release();
4965       tabPtr.p->fragments.release();
4966       ptr.p->tables.release();
4967       ptr.p->errorCode = 0;
4968       // fall-through
4969     }
4970   }
4971 
4972   if(!ptr.p->tables.seize(tabPtr) || !tabPtr.p->fragments.seize(1))
4973   {
4974     if(!tabPtr.isNull())
4975       ptr.p->tables.release();
4976     ndbrequire(false); // TODO
4977   }
4978   tabPtr.p->tableId = req.tableId;
4979   tabPtr.p->fragments.getPtr(fragPtr, 0);
4980   tabPtr.p->tableType = DictTabInfo::UserTable;
4981   fragPtr.p->fragmentId = req.fragmentId;
4982   fragPtr.p->lcp_no = req.lcpNo;
4983   fragPtr.p->scanned = 0;
4984   fragPtr.p->scanning = 0;
4985   fragPtr.p->tableId = req.tableId;
4986 
4987   ptr.p->backupId= req.backupId;
4988   lcp_open_file(signal, ptr);
4989 }
4990 
4991 void
lcp_close_file_conf(Signal * signal,BackupRecordPtr ptr)4992 Backup::lcp_close_file_conf(Signal* signal, BackupRecordPtr ptr)
4993 {
4994   jam();
4995 
4996   TablePtr tabPtr;
4997   ndbrequire(ptr.p->tables.first(tabPtr));
4998   Uint32 tableId = tabPtr.p->tableId;
4999 
5000   BackupFilePtr filePtr LINT_SET_PTR;
5001   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5002   ndbrequire(filePtr.p->m_flags == 0);
5003 
5004   if (ptr.p->m_gsn == GSN_LCP_PREPARE_REQ)
5005   {
5006     jam();
5007     defineBackupRef(signal, ptr, ptr.p->errorCode);
5008     return;
5009   }
5010 
5011   FragmentPtr fragPtr;
5012   tabPtr.p->fragments.getPtr(fragPtr, 0);
5013   Uint32 fragmentId = fragPtr.p->fragmentId;
5014 
5015   tabPtr.p->attributes.release();
5016   tabPtr.p->fragments.release();
5017   ptr.p->tables.release();
5018   ptr.p->errorCode = 0;
5019 
5020   BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
5021   conf->backupId = ptr.p->backupId;
5022   conf->backupPtr = ptr.i;
5023   conf->tableId = tableId;
5024   conf->fragmentNo = fragmentId;
5025   conf->noOfRecordsLow = 0;
5026   conf->noOfRecordsHigh = 0;
5027   conf->noOfBytesLow = 0;
5028   conf->noOfBytesHigh = 0;
5029   sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
5030 	     BackupFragmentConf::SignalLength, JBB);
5031 }
5032 
5033 void
lcp_open_file(Signal * signal,BackupRecordPtr ptr)5034 Backup::lcp_open_file(Signal* signal, BackupRecordPtr ptr)
5035 {
5036   FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
5037   req->userReference = reference();
5038   req->fileFlags =
5039     FsOpenReq::OM_WRITEONLY |
5040     FsOpenReq::OM_TRUNCATE |
5041     FsOpenReq::OM_CREATE |
5042     FsOpenReq::OM_APPEND |
5043     FsOpenReq::OM_AUTOSYNC;
5044   if (c_defaults.m_o_direct)
5045     req->fileFlags |= FsOpenReq::OM_DIRECT;
5046   FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
5047   req->auto_sync_size = c_defaults.m_disk_synch_size;
5048 
5049   TablePtr tabPtr;
5050   FragmentPtr fragPtr;
5051 
5052   ndbrequire(ptr.p->tables.first(tabPtr));
5053   tabPtr.p->fragments.getPtr(fragPtr, 0);
5054 
5055   /**
5056    * Lcp file
5057    */
5058   BackupFilePtr filePtr LINT_SET_PTR;
5059   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5060   ndbrequire(filePtr.p->m_flags == 0);
5061   filePtr.p->m_flags |= BackupFile::BF_OPENING;
5062   filePtr.p->tableId = RNIL; // Will force init
5063   req->userPointer = filePtr.i;
5064   FsOpenReq::setVersion(req->fileNumber, 5);
5065   FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
5066   FsOpenReq::v5_setLcpNo(req->fileNumber, fragPtr.p->lcp_no);
5067   FsOpenReq::v5_setTableId(req->fileNumber, tabPtr.p->tableId);
5068   FsOpenReq::v5_setFragmentId(req->fileNumber, fragPtr.p->fragmentId);
5069   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
5070 }
5071 
5072 void
lcp_open_file_done(Signal * signal,BackupRecordPtr ptr)5073 Backup::lcp_open_file_done(Signal* signal, BackupRecordPtr ptr)
5074 {
5075   TablePtr tabPtr;
5076   FragmentPtr fragPtr;
5077 
5078   ndbrequire(ptr.p->tables.first(tabPtr));
5079   tabPtr.p->fragments.getPtr(fragPtr, 0);
5080 
5081   BackupFilePtr filePtr LINT_SET_PTR;
5082   c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5083   ndbrequire(filePtr.p->m_flags ==
5084 	     (BackupFile::BF_OPEN | BackupFile::BF_LCP_META));
5085   filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
5086 
5087   ptr.p->slaveState.setState(STARTED);
5088 
5089   LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtrSend();
5090   conf->senderData = ptr.p->clientData;
5091   conf->senderRef = reference();
5092   conf->tableId = tabPtr.p->tableId;
5093   conf->fragmentId = fragPtr.p->fragmentId;
5094   sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_CONF,
5095 	     signal, LcpPrepareConf::SignalLength, JBB);
5096 
5097   /**
5098    * Start file thread
5099    */
5100   filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
5101 
5102   signal->theData[0] = BackupContinueB::START_FILE_THREAD;
5103   signal->theData[1] = filePtr.i;
5104   signal->theData[2] = __LINE__;
5105   sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
5106 }
5107 
5108 void
execEND_LCPREQ(Signal * signal)5109 Backup::execEND_LCPREQ(Signal* signal)
5110 {
5111   EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
5112 
5113   BackupRecordPtr ptr LINT_SET_PTR;
5114   c_backupPool.getPtr(ptr, req->backupPtr);
5115   ndbrequire(ptr.p->backupId == req->backupId);
5116 
5117   BackupFilePtr filePtr LINT_SET_PTR;
5118   ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
5119   ndbrequire(filePtr.p->m_flags == 0);
5120 
5121   if (!ptr.p->tables.isEmpty())
5122   {
5123     jam();
5124     ndbrequire(ptr.p->errorCode);
5125     TablePtr tabPtr;
5126     ptr.p->tables.first(tabPtr);
5127     tabPtr.p->attributes.release();
5128     tabPtr.p->fragments.release();
5129     ptr.p->tables.release();
5130     ptr.p->errorCode = 0;
5131   }
5132 
5133   ptr.p->errorCode = 0;
5134   ptr.p->slaveState.setState(CLEANING);
5135   ptr.p->slaveState.setState(INITIAL);
5136   ptr.p->slaveState.setState(DEFINING);
5137   ptr.p->slaveState.setState(DEFINED);
5138 
5139   EndLcpConf* conf= (EndLcpConf*)signal->getDataPtr();
5140   conf->senderData = ptr.p->clientData;
5141   conf->senderRef = reference();
5142   sendSignal(ptr.p->masterRef, GSN_END_LCPCONF,
5143 	     signal, EndLcpConf::SignalLength, JBB);
5144 }
5145