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