mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / kernel / blocks / backup / Backup.cpp
blobb607422b35cde09dada42b2015f560720951f339
1 /* Copyright (c) 2003-2008 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include <my_config.h>
17 #include "Backup.hpp"
19 #include <ndb_version.h>
21 #include <NdbTCP.h>
22 #include <Bitmask.hpp>
24 #include <signaldata/NodeFailRep.hpp>
25 #include <signaldata/ReadNodesConf.hpp>
27 #include <signaldata/DihFragCount.hpp>
28 #include <signaldata/ScanFrag.hpp>
30 #include <signaldata/GetTabInfo.hpp>
31 #include <signaldata/DictTabInfo.hpp>
32 #include <signaldata/ListTables.hpp>
34 #include <signaldata/FsOpenReq.hpp>
35 #include <signaldata/FsAppendReq.hpp>
36 #include <signaldata/FsCloseReq.hpp>
37 #include <signaldata/FsConf.hpp>
38 #include <signaldata/FsRef.hpp>
39 #include <signaldata/FsRemoveReq.hpp>
41 #include <signaldata/BackupImpl.hpp>
42 #include <signaldata/BackupSignalData.hpp>
43 #include <signaldata/BackupContinueB.hpp>
44 #include <signaldata/EventReport.hpp>
46 #include <signaldata/UtilSequence.hpp>
48 #include <signaldata/CreateTrig.hpp>
49 #include <signaldata/AlterTrig.hpp>
50 #include <signaldata/DropTrig.hpp>
51 #include <signaldata/FireTrigOrd.hpp>
52 #include <signaldata/TrigAttrInfo.hpp>
53 #include <AttributeHeader.hpp>
55 #include <signaldata/WaitGCP.hpp>
56 #include <signaldata/LCP.hpp>
58 #include <NdbTick.h>
60 static NDB_TICKS startTime;
62 static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
64 #ifdef VM_TRACE
65 #define DEBUG_OUT(x) ndbout << x << endl
66 #else
67 #define DEBUG_OUT(x)
68 #endif
70 //#define DEBUG_ABORT
71 //#define dbg globalSignalLoggers.log
73 static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
75 #define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
76 #define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
78 void
79 Backup::execSTTOR(Signal* signal)
81 jamEntry();
83 const Uint32 startphase = signal->theData[1];
84 const Uint32 typeOfStart = signal->theData[7];
86 if (startphase == 1)
88 m_curr_disk_write_speed = c_defaults.m_disk_write_speed_sr;
89 m_overflow_disk_write = 0;
90 m_reset_disk_speed_time = NdbTick_CurrentMillisecond();
91 m_reset_delay_used = Backup::DISK_SPEED_CHECK_DELAY;
92 signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
93 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
94 Backup::DISK_SPEED_CHECK_DELAY, 1);
96 if (startphase == 3) {
97 jam();
98 g_TypeOfStart = typeOfStart;
99 signal->theData[0] = reference();
100 sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
101 return;
102 }//if
104 if (startphase == 7)
106 m_curr_disk_write_speed = c_defaults.m_disk_write_speed;
109 if(startphase == 7 && g_TypeOfStart == NodeState::ST_INITIAL_START &&
110 c_masterNodeId == getOwnNodeId()){
111 jam();
112 createSequence(signal);
113 return;
114 }//if
116 sendSTTORRY(signal);
117 return;
118 }//Dbdict::execSTTOR()
120 void
121 Backup::execREAD_NODESCONF(Signal* signal)
123 jamEntry();
124 ReadNodesConf * conf = (ReadNodesConf *)signal->getDataPtr();
126 c_aliveNodes.clear();
128 Uint32 count = 0;
129 for (Uint32 i = 0; i<MAX_NDB_NODES; i++) {
130 jam();
131 if(NodeBitmask::get(conf->allNodes, i)){
132 jam();
133 count++;
135 NodePtr node;
136 ndbrequire(c_nodes.seize(node));
138 node.p->nodeId = i;
139 if(NodeBitmask::get(conf->inactiveNodes, i)) {
140 jam();
141 node.p->alive = 0;
142 } else {
143 jam();
144 node.p->alive = 1;
145 c_aliveNodes.set(i);
146 }//if
147 }//if
148 }//for
149 c_masterNodeId = conf->masterNodeId;
150 ndbrequire(count == conf->noOfNodes);
151 sendSTTORRY(signal);
154 void
155 Backup::sendSTTORRY(Signal* signal)
157 signal->theData[0] = 0;
158 signal->theData[3] = 1;
159 signal->theData[4] = 3;
160 signal->theData[5] = 7;
161 signal->theData[6] = 255; // No more start phases from missra
162 sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
165 void
166 Backup::createSequence(Signal* signal)
168 UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
170 req->senderData = RNIL;
171 req->sequenceId = BACKUP_SEQUENCE;
172 req->requestType = UtilSequenceReq::Create;
174 sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
175 signal, UtilSequenceReq::SignalLength, JBB);
178 void
179 Backup::execCONTINUEB(Signal* signal)
181 jamEntry();
182 const Uint32 Tdata0 = signal->theData[0];
183 const Uint32 Tdata1 = signal->theData[1];
184 const Uint32 Tdata2 = signal->theData[2];
186 switch(Tdata0) {
187 case BackupContinueB::RESET_DISK_SPEED_COUNTER:
190 Adjust for upto 10 millisecond delay of this signal. Longer
191 delays will not be handled, in this case the system is most
192 likely under too high load and it won't matter very much that
193 we decrease the speed of checkpoints.
195 We use a technique where we allow an overflow write in one
196 period. This overflow will be removed from the next period
197 such that the load will at average be as specified.
199 int delay_time = m_reset_delay_used;
200 NDB_TICKS curr_time = NdbTick_CurrentMillisecond();
201 int sig_delay = curr_time - m_reset_disk_speed_time;
203 m_words_written_this_period = m_overflow_disk_write;
204 m_overflow_disk_write = 0;
205 m_reset_disk_speed_time = curr_time;
207 if (sig_delay > delay_time + 10)
208 delay_time = Backup::DISK_SPEED_CHECK_DELAY - 10;
209 else if (sig_delay < delay_time - 10)
210 delay_time = Backup::DISK_SPEED_CHECK_DELAY + 10;
211 else
212 delay_time = Backup::DISK_SPEED_CHECK_DELAY - (sig_delay - delay_time);
213 m_reset_delay_used= delay_time;
214 signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
215 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, delay_time, 1);
216 #if 0
217 ndbout << "Signal delay was = " << sig_delay;
218 ndbout << " Current time = " << curr_time << endl;
219 ndbout << " Delay time will be = " << delay_time << endl << endl;
220 #endif
221 break;
223 case BackupContinueB::BACKUP_FRAGMENT_INFO:
225 jam();
226 const Uint32 ptr_I = Tdata1;
227 Uint32 tabPtr_I = Tdata2;
228 Uint32 fragPtr_I = signal->theData[3];
230 BackupRecordPtr ptr LINT_SET_PTR;
231 c_backupPool.getPtr(ptr, ptr_I);
232 TablePtr tabPtr;
233 ptr.p->tables.getPtr(tabPtr, tabPtr_I);
235 if (fragPtr_I != tabPtr.p->fragments.getSize())
237 jam();
238 FragmentPtr fragPtr;
239 tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I);
241 BackupFilePtr filePtr LINT_SET_PTR;
242 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
244 const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2;
245 Uint32 * dst;
246 if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz))
248 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4);
249 return;
252 BackupFormat::CtlFile::FragmentInfo * fragInfo =
253 (BackupFormat::CtlFile::FragmentInfo*)dst;
254 fragInfo->SectionType = htonl(BackupFormat::FRAGMENT_INFO);
255 fragInfo->SectionLength = htonl(sz);
256 fragInfo->TableId = htonl(fragPtr.p->tableId);
257 fragInfo->FragmentNo = htonl(fragPtr_I);
258 fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF);
259 fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32);
260 fragInfo->FilePosLow = htonl(0);
261 fragInfo->FilePosHigh = htonl(0);
263 filePtr.p->operation.dataBuffer.updateWritePtr(sz);
265 fragPtr_I++;
268 if (fragPtr_I == tabPtr.p->fragments.getSize())
270 signal->theData[0] = tabPtr.p->tableId;
271 signal->theData[1] = 0; // unlock
272 EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
274 fragPtr_I = 0;
275 ptr.p->tables.next(tabPtr);
276 if ((tabPtr_I = tabPtr.i) == RNIL)
278 jam();
279 closeFiles(signal, ptr);
280 return;
284 signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
285 signal->theData[1] = ptr_I;
286 signal->theData[2] = tabPtr_I;
287 signal->theData[3] = fragPtr_I;
288 sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
289 return;
291 case BackupContinueB::START_FILE_THREAD:
292 case BackupContinueB::BUFFER_UNDERFLOW:
294 jam();
295 BackupFilePtr filePtr LINT_SET_PTR;
296 c_backupFilePool.getPtr(filePtr, Tdata1);
297 checkFile(signal, filePtr);
298 return;
300 break;
301 case BackupContinueB::BUFFER_FULL_SCAN:
303 jam();
304 BackupFilePtr filePtr LINT_SET_PTR;
305 c_backupFilePool.getPtr(filePtr, Tdata1);
306 checkScan(signal, filePtr);
307 return;
309 break;
310 case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE:
312 jam();
313 BackupFilePtr filePtr LINT_SET_PTR;
314 c_backupFilePool.getPtr(filePtr, Tdata1);
315 fragmentCompleted(signal, filePtr);
316 return;
318 break;
319 case BackupContinueB::BUFFER_FULL_META:
321 jam();
322 BackupRecordPtr ptr LINT_SET_PTR;
323 c_backupPool.getPtr(ptr, Tdata1);
325 BackupFilePtr filePtr LINT_SET_PTR;
326 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
327 FsBuffer & buf = filePtr.p->operation.dataBuffer;
329 if(buf.getFreeSize() < buf.getMaxWrite()) {
330 jam();
331 TablePtr tabPtr LINT_SET_PTR;
332 c_tablePool.getPtr(tabPtr, Tdata2);
334 DEBUG_OUT("Backup - Buffer full - "
335 << buf.getFreeSize()
336 << " < " << buf.getMaxWrite()
337 << " (sz: " << buf.getUsableSize()
338 << " getMinRead: " << buf.getMinRead()
339 << ") - tableId = " << tabPtr.p->tableId);
341 signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
342 signal->theData[1] = Tdata1;
343 signal->theData[2] = Tdata2;
344 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
345 return;
346 }//if
348 TablePtr tabPtr LINT_SET_PTR;
349 c_tablePool.getPtr(tabPtr, Tdata2);
350 GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
351 req->senderRef = reference();
352 req->senderData = ptr.i;
353 req->requestType = GetTabInfoReq::RequestById |
354 GetTabInfoReq::LongSignalConf;
355 req->tableId = tabPtr.p->tableId;
356 sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
357 GetTabInfoReq::SignalLength, JBB);
358 return;
360 case BackupContinueB::ZDELAY_SCAN_NEXT:
361 if (ERROR_INSERTED(10036))
363 jam();
364 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 300,
365 signal->getLength());
366 return;
368 else
370 jam();
371 CLEAR_ERROR_INSERT_VALUE;
372 ndbout_c("Resuming backup");
373 memmove(signal->theData, signal->theData + 1,
374 4*ScanFragNextReq::SignalLength);
375 sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
376 ScanFragNextReq::SignalLength, JBB);
377 return ;
379 default:
380 ndbrequire(0);
381 }//switch
384 void
385 Backup::execDUMP_STATE_ORD(Signal* signal)
387 jamEntry();
389 if(signal->theData[0] == 20){
390 if(signal->length() > 1){
391 c_defaults.m_dataBufferSize = (signal->theData[1] * 1024 * 1024);
393 if(signal->length() > 2){
394 c_defaults.m_logBufferSize = (signal->theData[2] * 1024 * 1024);
396 if(signal->length() > 3){
397 c_defaults.m_minWriteSize = signal->theData[3] * 1024;
399 if(signal->length() > 4){
400 c_defaults.m_maxWriteSize = signal->theData[4] * 1024;
403 infoEvent("Backup: data: %d log: %d min: %d max: %d",
404 c_defaults.m_dataBufferSize,
405 c_defaults.m_logBufferSize,
406 c_defaults.m_minWriteSize,
407 c_defaults.m_maxWriteSize);
408 return;
410 if(signal->theData[0] == 21){
411 BackupReq * req = (BackupReq*)signal->getDataPtrSend();
412 req->senderData = 23;
413 req->backupDataLen = 0;
414 sendSignal(BACKUP_REF, GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
415 startTime = NdbTick_CurrentMillisecond();
416 return;
419 if(signal->theData[0] == 22){
420 const Uint32 seq = signal->theData[1];
421 FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
422 req->userReference = reference();
423 req->userPointer = 23;
424 req->directory = 1;
425 req->ownDirectory = 1;
426 FsOpenReq::setVersion(req->fileNumber, 2);
427 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
428 FsOpenReq::v2_setSequence(req->fileNumber, seq);
429 FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
430 sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
431 FsRemoveReq::SignalLength, JBA);
432 return;
435 if(signal->theData[0] == 23){
437 * Print records
439 BackupRecordPtr ptr LINT_SET_PTR;
440 for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){
441 infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x",
442 ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
443 infoEvent(" State: %d", ptr.p->slaveState.getState());
444 BackupFilePtr filePtr;
445 for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
446 ptr.p->files.next(filePtr)){
447 jam();
448 infoEvent(" file %d: type: %d flags: H'%x",
449 filePtr.i, filePtr.p->fileType,
450 filePtr.p->m_flags);
454 ndbout_c("m_curr_disk_write_speed: %u m_words_written_this_period: %u m_overflow_disk_write: %u",
455 m_curr_disk_write_speed, m_words_written_this_period, m_overflow_disk_write);
456 ndbout_c("m_reset_delay_used: %u m_reset_disk_speed_time: %llu",
457 m_reset_delay_used, (Uint64)m_reset_disk_speed_time);
458 for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr))
460 ndbout_c("BackupRecord %u: BackupId: %u MasterRef: %x ClientRef: %x",
461 ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
462 ndbout_c(" State: %u", ptr.p->slaveState.getState());
463 ndbout_c(" noOfByte: %llu noOfRecords: %llu",
464 ptr.p->noOfBytes, ptr.p->noOfRecords);
465 ndbout_c(" noOfLogBytes: %llu noOfLogRecords: %llu",
466 ptr.p->noOfLogBytes, ptr.p->noOfLogRecords);
467 ndbout_c(" errorCode: %u", ptr.p->errorCode);
468 BackupFilePtr filePtr;
469 for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
470 ptr.p->files.next(filePtr))
472 ndbout_c(" file %u: type: %u flags: H'%x tableId: %u fragmentId: %u",
473 filePtr.i, filePtr.p->fileType, filePtr.p->m_flags,
474 filePtr.p->tableId, filePtr.p->fragmentNo);
476 if (ptr.p->slaveState.getState() == SCANNING && ptr.p->dataFilePtr != RNIL)
478 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
479 OperationRecord & op = filePtr.p->operation;
480 Uint32 *tmp = NULL;
481 Uint32 sz = 0;
482 bool eof = FALSE;
483 bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
484 ndbout_c("ready: %s eof: %s", ready ? "TRUE" : "FALSE", eof ? "TRUE" : "FALSE");
487 return;
489 if(signal->theData[0] == 24){
491 * Print size of records etc.
493 infoEvent("Backup - dump pool sizes");
494 infoEvent("BackupPool: %d BackupFilePool: %d TablePool: %d",
495 c_backupPool.getSize(), c_backupFilePool.getSize(),
496 c_tablePool.getSize());
497 infoEvent("AttrPool: %d TriggerPool: %d FragmentPool: %d",
498 c_backupPool.getSize(), c_backupFilePool.getSize(),
499 c_tablePool.getSize());
500 infoEvent("PagePool: %d",
501 c_pagePool.getSize());
504 if(signal->getLength() == 2 && signal->theData[1] == 2424)
507 * Handle LCP
509 BackupRecordPtr lcp;
510 ndbrequire(c_backups.first(lcp));
512 ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree() + 1);
513 if(lcp.p->tables.isEmpty())
515 ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree());
516 ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree());
517 ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree());
518 ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree());
520 ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree() + 1);
521 BackupFilePtr lcp_file;
522 c_backupFilePool.getPtr(lcp_file, lcp.p->dataFilePtr);
523 ndbrequire(c_pagePool.getSize() ==
524 c_pagePool.getNoOfFree() +
525 lcp_file.p->pages.getSize());
530 bool
531 Backup::findTable(const BackupRecordPtr & ptr,
532 TablePtr & tabPtr, Uint32 tableId) const
534 for(ptr.p->tables.first(tabPtr);
535 tabPtr.i != RNIL;
536 ptr.p->tables.next(tabPtr)) {
537 jam();
538 if(tabPtr.p->tableId == tableId){
539 jam();
540 return true;
541 }//if
542 }//for
543 tabPtr.i = RNIL;
544 tabPtr.p = 0;
545 return false;
548 static Uint32 xps(Uint64 x, Uint64 ms)
550 float fx = x;
551 float fs = ms;
553 if(ms == 0 || x == 0) {
554 jam();
555 return 0;
556 }//if
557 jam();
558 return ((Uint32)(1000.0f * (fx + fs/2.1f))) / ((Uint32)fs);
561 struct Number {
562 Number(Uint64 r) { val = r;}
563 Number & operator=(Uint64 r) { val = r; return * this; }
564 Uint64 val;
567 NdbOut &
568 operator<< (NdbOut & out, const Number & val){
569 char p = 0;
570 Uint32 loop = 1;
571 while(val.val > loop){
572 loop *= 1000;
573 p += 3;
575 if(loop != 1){
576 p -= 3;
577 loop /= 1000;
580 switch(p){
581 case 0:
582 break;
583 case 3:
584 p = 'k';
585 break;
586 case 6:
587 p = 'M';
588 break;
589 case 9:
590 p = 'G';
591 break;
592 default:
593 p = 0;
595 char str[2];
596 str[0] = p;
597 str[1] = 0;
598 Uint32 tmp = (val.val + (loop >> 1)) / loop;
599 #if 1
600 if(p > 0)
601 out << tmp << str;
602 else
603 out << tmp;
604 #else
605 out << val.val;
606 #endif
608 return out;
611 void
612 Backup::execBACKUP_CONF(Signal* signal)
614 jamEntry();
615 BackupConf * conf = (BackupConf*)signal->getDataPtr();
617 ndbout_c("Backup %d has started", conf->backupId);
620 void
621 Backup::execBACKUP_REF(Signal* signal)
623 jamEntry();
624 BackupRef * ref = (BackupRef*)signal->getDataPtr();
626 ndbout_c("Backup (%d) has NOT started %d", ref->senderData, ref->errorCode);
629 void
630 Backup::execBACKUP_COMPLETE_REP(Signal* signal)
632 jamEntry();
633 BackupCompleteRep* rep = (BackupCompleteRep*)signal->getDataPtr();
635 startTime = NdbTick_CurrentMillisecond() - startTime;
637 ndbout_c("Backup %d has completed", rep->backupId);
638 const Uint64 bytes =
639 rep->noOfBytesLow + (((Uint64)rep->noOfBytesHigh) << 32);
640 const Uint64 records =
641 rep->noOfRecordsLow + (((Uint64)rep->noOfRecordsHigh) << 32);
643 Number rps = xps(records, startTime);
644 Number bps = xps(bytes, startTime);
646 ndbout << " Data [ "
647 << Number(records) << " rows "
648 << Number(bytes) << " bytes " << startTime << " ms ] "
649 << " => "
650 << rps << " row/s & " << bps << "b/s" << endl;
652 bps = xps(rep->noOfLogBytes, startTime);
653 rps = xps(rep->noOfLogRecords, startTime);
655 ndbout << " Log [ "
656 << Number(rep->noOfLogRecords) << " log records "
657 << Number(rep->noOfLogBytes) << " bytes " << startTime << " ms ] "
658 << " => "
659 << rps << " records/s & " << bps << "b/s" << endl;
663 void
664 Backup::execBACKUP_ABORT_REP(Signal* signal)
666 jamEntry();
667 BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtr();
669 ndbout_c("Backup %d has been aborted %d", rep->backupId, rep->reason);
672 const TriggerEvent::Value triggerEventValues[] = {
673 TriggerEvent::TE_INSERT,
674 TriggerEvent::TE_UPDATE,
675 TriggerEvent::TE_DELETE
678 const Backup::State
679 Backup::validSlaveTransitions[] = {
680 INITIAL, DEFINING,
681 DEFINING, DEFINED,
682 DEFINED, STARTED,
683 STARTED, STARTED, // Several START_BACKUP_REQ is sent
684 STARTED, SCANNING,
685 SCANNING, STARTED,
686 STARTED, STOPPING,
687 STOPPING, CLEANING,
688 CLEANING, INITIAL,
690 INITIAL, ABORTING, // Node fail
691 DEFINING, ABORTING,
692 DEFINED, ABORTING,
693 STARTED, ABORTING,
694 SCANNING, ABORTING,
695 STOPPING, ABORTING,
696 CLEANING, ABORTING, // Node fail w/ master takeover
697 ABORTING, ABORTING, // Slave who initiates ABORT should have this transition
699 ABORTING, INITIAL,
700 INITIAL, INITIAL
703 const Uint32
704 Backup::validSlaveTransitionsCount =
705 sizeof(Backup::validSlaveTransitions) / sizeof(Backup::State);
707 void
708 Backup::CompoundState::setState(State newState){
709 bool found = false;
710 const State currState = state;
711 for(unsigned i = 0; i<noOfValidTransitions; i+= 2) {
712 jam();
713 if(validTransitions[i] == currState &&
714 validTransitions[i+1] == newState){
715 jam();
716 found = true;
717 break;
721 //ndbrequire(found);
723 if (newState == INITIAL)
724 abortState = INITIAL;
725 if(newState == ABORTING && currState != ABORTING) {
726 jam();
727 abortState = currState;
729 state = newState;
730 #ifdef DEBUG_ABORT
731 if (newState != currState) {
732 ndbout_c("%u: Old state = %u, new state = %u, abort state = %u",
733 id, currState, newState, abortState);
735 #endif
738 void
739 Backup::CompoundState::forceState(State newState)
741 const State currState = state;
742 if (newState == INITIAL)
743 abortState = INITIAL;
744 if(newState == ABORTING && currState != ABORTING) {
745 jam();
746 abortState = currState;
748 state = newState;
749 #ifdef DEBUG_ABORT
750 if (newState != currState) {
751 ndbout_c("%u: FORCE: Old state = %u, new state = %u, abort state = %u",
752 id, currState, newState, abortState);
754 #endif
757 Backup::Table::Table(ArrayPool<Attribute> & ah,
758 ArrayPool<Fragment> & fh)
759 : attributes(ah), fragments(fh)
761 triggerIds[0] = ILLEGAL_TRIGGER_ID;
762 triggerIds[1] = ILLEGAL_TRIGGER_ID;
763 triggerIds[2] = ILLEGAL_TRIGGER_ID;
764 triggerAllocated[0] = false;
765 triggerAllocated[1] = false;
766 triggerAllocated[2] = false;
769 /*****************************************************************************
771 * Node state handling
773 *****************************************************************************/
774 void
775 Backup::execNODE_FAILREP(Signal* signal)
777 jamEntry();
779 NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
781 bool doStuff = false;
783 Start by saving important signal data which will be destroyed before the
784 process is completed.
786 NodeId new_master_node_id = rep->masterNodeId;
787 Uint32 theFailedNodes[NodeBitmask::Size];
788 for (Uint32 i = 0; i < NodeBitmask::Size; i++)
789 theFailedNodes[i] = rep->theNodes[i];
791 c_masterNodeId = new_master_node_id;
793 NodePtr nodePtr;
794 for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
795 jam();
796 if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)){
797 if(nodePtr.p->alive){
798 jam();
799 ndbrequire(c_aliveNodes.get(nodePtr.p->nodeId));
800 doStuff = true;
801 } else {
802 jam();
803 ndbrequire(!c_aliveNodes.get(nodePtr.p->nodeId));
804 }//if
805 nodePtr.p->alive = 0;
806 c_aliveNodes.clear(nodePtr.p->nodeId);
807 }//if
808 }//for
810 if(!doStuff){
811 jam();
812 return;
813 }//if
815 #ifdef DEBUG_ABORT
816 ndbout_c("****************** Node fail rep ******************");
817 #endif
819 NodeId newCoordinator = c_masterNodeId;
820 BackupRecordPtr ptr;
821 for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
822 jam();
823 checkNodeFail(signal, ptr, newCoordinator, theFailedNodes);
827 bool
828 Backup::verifyNodesAlive(BackupRecordPtr ptr,
829 const NdbNodeBitmask& aNodeBitMask)
831 Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
832 for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
833 jam();
834 if(aNodeBitMask.get(i)) {
835 if(!c_aliveNodes.get(i)){
836 jam();
837 ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
838 return false;
839 }//if
840 if(getNodeInfo(i).m_version != version)
842 jam();
843 ptr.p->setErrorCode(AbortBackupOrd::IncompatibleVersions);
844 return false;
846 }//if
847 }//for
848 return true;
851 void
852 Backup::checkNodeFail(Signal* signal,
853 BackupRecordPtr ptr,
854 NodeId newCoord,
855 Uint32 theFailedNodes[NodeBitmask::Size])
857 NdbNodeBitmask mask;
858 mask.assign(2, theFailedNodes);
860 /* Update ptr.p->nodes to be up to date with current alive nodes
862 NodePtr nodePtr;
863 bool found = false;
864 for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
865 jam();
866 if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)) {
867 jam();
868 if (ptr.p->nodes.get(nodePtr.p->nodeId)) {
869 jam();
870 ptr.p->nodes.clear(nodePtr.p->nodeId);
871 found = true;
873 }//if
874 }//for
876 if(!found) {
877 jam();
878 return; // failed node is not part of backup process, safe to continue
881 if(mask.get(refToNode(ptr.p->masterRef)))
884 * Master died...abort
886 ptr.p->masterRef = reference();
887 ptr.p->nodes.clear();
888 ptr.p->nodes.set(getOwnNodeId());
889 ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
890 switch(ptr.p->m_gsn){
891 case GSN_DEFINE_BACKUP_REQ:
892 case GSN_START_BACKUP_REQ:
893 case GSN_BACKUP_FRAGMENT_REQ:
894 case GSN_STOP_BACKUP_REQ:
895 // I'm currently processing...reply to self and abort...
896 ptr.p->masterData.gsn = ptr.p->m_gsn;
897 ptr.p->masterData.sendCounter = ptr.p->nodes;
898 return;
899 case GSN_DEFINE_BACKUP_REF:
900 case GSN_DEFINE_BACKUP_CONF:
901 case GSN_START_BACKUP_REF:
902 case GSN_START_BACKUP_CONF:
903 case GSN_BACKUP_FRAGMENT_REF:
904 case GSN_BACKUP_FRAGMENT_CONF:
905 case GSN_STOP_BACKUP_REF:
906 case GSN_STOP_BACKUP_CONF:
907 ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
908 masterAbort(signal, ptr);
909 return;
910 case GSN_ABORT_BACKUP_ORD:
911 // Already aborting
912 return;
915 else if (newCoord == getOwnNodeId())
918 * I'm master for this backup
920 jam();
921 CRASH_INSERTION((10001));
922 #ifdef DEBUG_ABORT
923 ndbout_c("**** Master: Node failed: Master id = %u",
924 refToNode(ptr.p->masterRef));
925 #endif
927 Uint32 gsn, len, pos;
928 LINT_INIT(gsn);
929 LINT_INIT(len);
930 LINT_INIT(pos);
931 ptr.p->nodes.bitANDC(mask);
932 switch(ptr.p->masterData.gsn){
933 case GSN_DEFINE_BACKUP_REQ:
935 DefineBackupRef * ref = (DefineBackupRef*)signal->getDataPtr();
936 ref->backupPtr = ptr.i;
937 ref->backupId = ptr.p->backupId;
938 ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
939 gsn= GSN_DEFINE_BACKUP_REF;
940 len= DefineBackupRef::SignalLength;
941 pos= &ref->nodeId - signal->getDataPtr();
942 break;
944 case GSN_START_BACKUP_REQ:
946 StartBackupRef * ref = (StartBackupRef*)signal->getDataPtr();
947 ref->backupPtr = ptr.i;
948 ref->backupId = ptr.p->backupId;
949 ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
950 gsn= GSN_START_BACKUP_REF;
951 len= StartBackupRef::SignalLength;
952 pos= &ref->nodeId - signal->getDataPtr();
953 break;
955 case GSN_BACKUP_FRAGMENT_REQ:
957 BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
958 ref->backupPtr = ptr.i;
959 ref->backupId = ptr.p->backupId;
960 ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
961 gsn= GSN_BACKUP_FRAGMENT_REF;
962 len= BackupFragmentRef::SignalLength;
963 pos= &ref->nodeId - signal->getDataPtr();
964 break;
966 case GSN_STOP_BACKUP_REQ:
968 StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
969 ref->backupPtr = ptr.i;
970 ref->backupId = ptr.p->backupId;
971 ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
972 ref->nodeId = getOwnNodeId();
973 gsn= GSN_STOP_BACKUP_REF;
974 len= StopBackupRef::SignalLength;
975 pos= &ref->nodeId - signal->getDataPtr();
976 break;
978 case GSN_WAIT_GCP_REQ:
979 case GSN_DROP_TRIG_REQ:
980 case GSN_CREATE_TRIG_REQ:
981 case GSN_ALTER_TRIG_REQ:
982 ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
983 return;
984 case GSN_UTIL_SEQUENCE_REQ:
985 case GSN_UTIL_LOCK_REQ:
986 return;
987 default:
988 ndbrequire(false);
991 for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; )
993 signal->theData[pos] = i;
994 sendSignal(reference(), gsn, signal, len, JBB);
995 #ifdef DEBUG_ABORT
996 ndbout_c("sending %d to self from %d", gsn, i);
997 #endif
999 return;
1000 }//if
1003 * I abort myself as slave if not master
1005 CRASH_INSERTION((10021));
1008 void
1009 Backup::execINCL_NODEREQ(Signal* signal)
1011 jamEntry();
1013 const Uint32 senderRef = signal->theData[0];
1014 const Uint32 inclNode = signal->theData[1];
1016 NodePtr node;
1017 for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
1018 jam();
1019 const Uint32 nodeId = node.p->nodeId;
1020 if(inclNode == nodeId){
1021 jam();
1023 ndbrequire(node.p->alive == 0);
1024 ndbrequire(!c_aliveNodes.get(nodeId));
1026 node.p->alive = 1;
1027 c_aliveNodes.set(nodeId);
1029 break;
1030 }//if
1031 }//for
1032 signal->theData[0] = inclNode;
1033 signal->theData[1] = reference();
1034 sendSignal(senderRef, GSN_INCL_NODECONF, signal, 2, JBB);
1037 /*****************************************************************************
1039 * Master functionallity - Define backup
1041 *****************************************************************************/
1043 void
1044 Backup::execBACKUP_REQ(Signal* signal)
1046 jamEntry();
1047 BackupReq * req = (BackupReq*)signal->getDataPtr();
1049 const Uint32 senderData = req->senderData;
1050 const BlockReference senderRef = signal->senderBlockRef();
1051 const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
1052 const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
1054 if(getOwnNodeId() != getMasterNodeId()) {
1055 jam();
1056 sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
1057 return;
1058 }//if
1060 if (c_defaults.m_diskless)
1062 sendBackupRef(senderRef, flags, signal, senderData,
1063 BackupRef::CannotBackupDiskless);
1064 return;
1067 if(dataLen32 != 0) {
1068 jam();
1069 sendBackupRef(senderRef, flags, signal, senderData,
1070 BackupRef::BackupDefinitionNotImplemented);
1071 return;
1072 }//if
1074 #ifdef DEBUG_ABORT
1075 dumpUsedResources();
1076 #endif
1078 * Seize a backup record
1080 BackupRecordPtr ptr;
1081 c_backups.seize(ptr);
1082 if(ptr.i == RNIL) {
1083 jam();
1084 sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
1085 return;
1086 }//if
1088 ndbrequire(ptr.p->tables.isEmpty());
1090 ptr.p->m_gsn = 0;
1091 ptr.p->errorCode = 0;
1092 ptr.p->clientRef = senderRef;
1093 ptr.p->clientData = senderData;
1094 ptr.p->flags = flags;
1095 ptr.p->masterRef = reference();
1096 ptr.p->nodes = c_aliveNodes;
1097 ptr.p->backupId = 0;
1098 ptr.p->backupKey[0] = 0;
1099 ptr.p->backupKey[1] = 0;
1100 ptr.p->backupDataLen = 0;
1101 ptr.p->masterData.errorCode = 0;
1103 UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
1105 ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ;
1106 utilReq->senderData = ptr.i;
1107 utilReq->sequenceId = BACKUP_SEQUENCE;
1108 utilReq->requestType = UtilSequenceReq::NextVal;
1109 sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
1110 signal, UtilSequenceReq::SignalLength, JBB);
1113 void
1114 Backup::execUTIL_SEQUENCE_REF(Signal* signal)
1116 BackupRecordPtr ptr LINT_SET_PTR;
1117 jamEntry();
1118 UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr();
1119 ptr.i = utilRef->senderData;
1120 c_backupPool.getPtr(ptr);
1121 ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
1122 sendBackupRef(signal, ptr, BackupRef::SequenceFailure);
1123 }//execUTIL_SEQUENCE_REF()
1126 void
1127 Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
1129 jam();
1130 sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
1131 cleanup(signal, ptr);
1134 void
1135 Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
1136 Uint32 senderData, Uint32 errorCode)
1138 jam();
1139 if (SEND_BACKUP_STARTED_FLAG(flags))
1141 BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
1142 ref->senderData = senderData;
1143 ref->errorCode = errorCode;
1144 ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
1145 sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
1148 if(errorCode != BackupRef::IAmNotMaster){
1149 signal->theData[0] = NDB_LE_BackupFailedToStart;
1150 signal->theData[1] = senderRef;
1151 signal->theData[2] = errorCode;
1152 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
1156 void
1157 Backup::execUTIL_SEQUENCE_CONF(Signal* signal)
1159 jamEntry();
1161 UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
1163 if(conf->requestType == UtilSequenceReq::Create)
1165 jam();
1166 sendSTTORRY(signal); // At startup in NDB
1167 return;
1170 BackupRecordPtr ptr LINT_SET_PTR;
1171 ptr.i = conf->senderData;
1172 c_backupPool.getPtr(ptr);
1174 ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
1176 if (ptr.p->checkError())
1178 jam();
1179 sendBackupRef(signal, ptr, ptr.p->errorCode);
1180 return;
1181 }//if
1183 if (ERROR_INSERTED(10023))
1185 sendBackupRef(signal, ptr, 323);
1186 return;
1187 }//if
1191 Uint64 backupId;
1192 memcpy(&backupId,conf->sequenceValue,8);
1193 ptr.p->backupId= (Uint32)backupId;
1195 ptr.p->backupKey[0] = (getOwnNodeId() << 16) | (ptr.p->backupId & 0xFFFF);
1196 ptr.p->backupKey[1] = NdbTick_CurrentMillisecond();
1198 ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
1199 Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1200 Callback c = { safe_cast(&Backup::defineBackupMutex_locked), ptr.i };
1201 ndbrequire(mutex.lock(c));
1203 return;
1206 void
1207 Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
1208 jamEntry();
1209 ndbrequire(retVal == 0);
1211 BackupRecordPtr ptr LINT_SET_PTR;
1212 ptr.i = ptrI;
1213 c_backupPool.getPtr(ptr);
1215 ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
1217 ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
1218 Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1219 Callback c = { safe_cast(&Backup::dictCommitTableMutex_locked), ptr.i };
1220 ndbrequire(mutex.lock(c));
1223 void
1224 Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal)
1226 jamEntry();
1227 ndbrequire(retVal == 0);
1230 * We now have both the mutexes
1232 BackupRecordPtr ptr LINT_SET_PTR;
1233 ptr.i = ptrI;
1234 c_backupPool.getPtr(ptr);
1236 ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
1238 if (ERROR_INSERTED(10031)) {
1239 ptr.p->setErrorCode(331);
1240 }//if
1242 if (ptr.p->checkError())
1244 jam();
1247 * Unlock mutexes
1249 jam();
1250 Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1251 jam();
1252 mutex1.unlock(); // ignore response
1254 jam();
1255 Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1256 jam();
1257 mutex2.unlock(); // ignore response
1259 sendBackupRef(signal, ptr, ptr.p->errorCode);
1260 return;
1261 }//if
1263 sendDefineBackupReq(signal, ptr);
1266 /*****************************************************************************
1268 * Master functionallity - Define backup cont'd (from now on all slaves are in)
1270 *****************************************************************************/
1272 bool
1273 Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId)
1275 ndbrequire(ptr.p->masterRef == reference());
1276 ndbrequire(ptr.p->masterData.gsn == gsn);
1277 ndbrequire(!ptr.p->masterData.sendCounter.done());
1278 ndbrequire(ptr.p->masterData.sendCounter.isWaitingFor(nodeId));
1280 ptr.p->masterData.sendCounter.clearWaitingFor(nodeId);
1281 return ptr.p->masterData.sendCounter.done();
1284 void
1285 Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
1288 * Sending define backup to all participants
1290 DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
1291 req->backupId = ptr.p->backupId;
1292 req->clientRef = ptr.p->clientRef;
1293 req->clientData = ptr.p->clientData;
1294 req->senderRef = reference();
1295 req->backupPtr = ptr.i;
1296 req->backupKey[0] = ptr.p->backupKey[0];
1297 req->backupKey[1] = ptr.p->backupKey[1];
1298 req->nodes = ptr.p->nodes;
1299 req->backupDataLen = ptr.p->backupDataLen;
1300 req->flags = ptr.p->flags;
1302 ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
1303 ptr.p->masterData.sendCounter = ptr.p->nodes;
1304 NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1305 sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal,
1306 DefineBackupReq::SignalLength, JBB);
1309 * Now send backup data
1311 const Uint32 len = ptr.p->backupDataLen;
1312 if(len == 0){
1314 * No data to send
1316 jam();
1317 return;
1318 }//if
1321 * Not implemented
1323 ndbrequire(0);
1326 void
1327 Backup::execDEFINE_BACKUP_REF(Signal* signal)
1329 jamEntry();
1331 DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtr();
1333 const Uint32 ptrI = ref->backupPtr;
1334 //const Uint32 backupId = ref->backupId;
1335 const Uint32 nodeId = ref->nodeId;
1337 BackupRecordPtr ptr LINT_SET_PTR;
1338 c_backupPool.getPtr(ptr, ptrI);
1340 ptr.p->setErrorCode(ref->errorCode);
1341 defineBackupReply(signal, ptr, nodeId);
1344 void
1345 Backup::execDEFINE_BACKUP_CONF(Signal* signal)
1347 jamEntry();
1349 DefineBackupConf* conf = (DefineBackupConf*)signal->getDataPtr();
1350 const Uint32 ptrI = conf->backupPtr;
1351 //const Uint32 backupId = conf->backupId;
1352 const Uint32 nodeId = refToNode(signal->senderBlockRef());
1354 BackupRecordPtr ptr LINT_SET_PTR;
1355 c_backupPool.getPtr(ptr, ptrI);
1357 if (ERROR_INSERTED(10024))
1359 ptr.p->setErrorCode(324);
1362 defineBackupReply(signal, ptr, nodeId);
1365 void
1366 Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
1368 if (!haveAllSignals(ptr, GSN_DEFINE_BACKUP_REQ, nodeId)) {
1369 jam();
1370 return;
1374 * Unlock mutexes
1376 jam();
1377 Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
1378 jam();
1379 mutex1.unlock(); // ignore response
1381 jam();
1382 Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
1383 jam();
1384 mutex2.unlock(); // ignore response
1386 if(ptr.p->checkError())
1388 jam();
1389 masterAbort(signal, ptr);
1390 return;
1394 * Reply to client
1396 CRASH_INSERTION((10034));
1398 if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
1400 BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
1401 conf->backupId = ptr.p->backupId;
1402 conf->senderData = ptr.p->clientData;
1403 conf->nodes = ptr.p->nodes;
1404 sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
1405 BackupConf::SignalLength, JBB);
1408 signal->theData[0] = NDB_LE_BackupStarted;
1409 signal->theData[1] = ptr.p->clientRef;
1410 signal->theData[2] = ptr.p->backupId;
1411 ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
1412 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
1415 * We've received GSN_DEFINE_BACKUP_CONF from all participants.
1417 * Our next step is to send START_BACKUP_REQ to all participants,
1418 * who will then send CREATE_TRIG_REQ for all tables to their local
1419 * DBTUP.
1421 TablePtr tabPtr;
1422 ptr.p->tables.first(tabPtr);
1424 sendStartBackup(signal, ptr, tabPtr);
1427 /*****************************************************************************
1429 * Master functionallity - Prepare triggers
1431 *****************************************************************************/
1432 void
1433 Backup::createAttributeMask(TablePtr tabPtr,
1434 Bitmask<MAXNROFATTRIBUTESINWORDS> & mask)
1436 mask.clear();
1437 Table & table = * tabPtr.p;
1438 Ptr<Attribute> attrPtr;
1439 table.attributes.first(attrPtr);
1440 for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
1442 jam();
1443 mask.set(attrPtr.p->data.attrId);
1447 void
1448 Backup::sendCreateTrig(Signal* signal,
1449 BackupRecordPtr ptr, TablePtr tabPtr)
1451 CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend();
1454 * First, setup the structures
1456 for(Uint32 j=0; j<3; j++) {
1457 jam();
1459 TriggerPtr trigPtr;
1460 if(!ptr.p->triggers.seize(trigPtr)) {
1461 jam();
1462 ptr.p->m_gsn = GSN_START_BACKUP_REF;
1463 StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
1464 ref->backupPtr = ptr.i;
1465 ref->backupId = ptr.p->backupId;
1466 ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
1467 ref->nodeId = getOwnNodeId();
1468 sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
1469 StartBackupRef::SignalLength, JBB);
1470 return;
1471 } // if
1473 const Uint32 triggerId= trigPtr.i;
1474 tabPtr.p->triggerIds[j] = triggerId;
1475 tabPtr.p->triggerAllocated[j] = true;
1476 trigPtr.p->backupPtr = ptr.i;
1477 trigPtr.p->tableId = tabPtr.p->tableId;
1478 trigPtr.p->tab_ptr_i = tabPtr.i;
1479 trigPtr.p->logEntry = 0;
1480 trigPtr.p->event = j;
1481 trigPtr.p->maxRecordSize = 4096;
1482 trigPtr.p->operation =
1483 &ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
1484 trigPtr.p->operation->noOfBytes = 0;
1485 trigPtr.p->operation->noOfRecords = 0;
1486 trigPtr.p->errorCode = 0;
1487 } // for
1490 * now ask DBTUP to create
1492 ptr.p->slaveData.gsn = GSN_CREATE_TRIG_REQ;
1493 ptr.p->slaveData.trigSendCounter = 3;
1494 ptr.p->slaveData.createTrig.tableId = tabPtr.p->tableId;
1496 req->setUserRef(reference());
1497 req->setReceiverRef(reference());
1498 req->setConnectionPtr(ptr.i);
1499 req->setRequestType(CreateTrigReq::RT_USER);
1501 Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask;
1502 createAttributeMask(tabPtr, attrMask);
1503 req->setAttributeMask(attrMask);
1504 req->setTableId(tabPtr.p->tableId);
1505 req->setIndexId(RNIL); // not used
1506 req->setTriggerType(TriggerType::SUBSCRIPTION);
1507 req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
1508 req->setMonitorReplicas(true);
1509 req->setMonitorAllAttributes(false);
1510 req->setOnline(true);
1512 for (int i=0; i < 3; i++) {
1513 req->setTriggerId(tabPtr.p->triggerIds[i]);
1514 req->setTriggerEvent(triggerEventValues[i]);
1516 sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
1517 signal, CreateTrigReq::SignalLength, JBB);
1521 void
1522 Backup::execCREATE_TRIG_CONF(Signal* signal)
1524 jamEntry();
1525 CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtr();
1527 const Uint32 ptrI = conf->getConnectionPtr();
1528 const Uint32 tableId = conf->getTableId();
1529 const TriggerEvent::Value type = conf->getTriggerEvent();
1531 BackupRecordPtr ptr LINT_SET_PTR;
1532 c_backupPool.getPtr(ptr, ptrI);
1535 * Verify that I'm waiting for this conf
1537 * ptr.p->masterRef != reference()
1538 * as slaves and masters have triggers now.
1540 ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
1541 ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
1542 ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
1544 TablePtr tabPtr;
1545 ndbrequire(findTable(ptr, tabPtr, tableId));
1546 ndbrequire(type < 3); // if some decides to change the enums
1548 createTrigReply(signal, ptr);
1551 void
1552 Backup::execCREATE_TRIG_REF(Signal* signal)
1554 jamEntry();
1555 CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr();
1557 const Uint32 ptrI = ref->getConnectionPtr();
1558 const Uint32 tableId = ref->getTableId();
1560 BackupRecordPtr ptr LINT_SET_PTR;
1561 c_backupPool.getPtr(ptr, ptrI);
1564 * Verify that I'm waiting for this ref
1566 * ptr.p->masterRef != reference()
1567 * as slaves and masters have triggers now
1569 ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
1570 ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
1571 ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
1573 ptr.p->setErrorCode(ref->getErrorCode());
1575 createTrigReply(signal, ptr);
1578 void
1579 Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
1581 CRASH_INSERTION(10003);
1584 * Check finished with table
1586 ptr.p->slaveData.trigSendCounter--;
1587 if(ptr.p->slaveData.trigSendCounter.done() == false){
1588 jam();
1589 return;
1590 }//if
1592 if (ERROR_INSERTED(10025))
1594 ptr.p->errorCode = 325;
1597 if(ptr.p->checkError()) {
1598 jam();
1599 ptr.p->m_gsn = GSN_START_BACKUP_REF;
1600 StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
1601 ref->backupPtr = ptr.i;
1602 ref->backupId = ptr.p->backupId;
1603 ref->errorCode = ptr.p->errorCode;
1604 ref->nodeId = getOwnNodeId();
1605 sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
1606 StartBackupRef::SignalLength, JBB);
1607 return;
1608 }//if
1610 TablePtr tabPtr;
1611 ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.createTrig.tableId));
1614 * Next table
1616 ptr.p->tables.next(tabPtr);
1617 if(tabPtr.i != RNIL){
1618 jam();
1619 sendCreateTrig(signal, ptr, tabPtr);
1620 return;
1621 }//if
1624 * We've finished creating triggers.
1626 * send conf and wait
1628 ptr.p->m_gsn = GSN_START_BACKUP_CONF;
1629 StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend();
1630 conf->backupPtr = ptr.i;
1631 conf->backupId = ptr.p->backupId;
1632 sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal,
1633 StartBackupConf::SignalLength, JBB);
1636 /*****************************************************************************
1638 * Master functionallity - Start backup
1640 *****************************************************************************/
1641 void
1642 Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
1645 ptr.p->masterData.startBackup.tablePtr = tabPtr.i;
1647 StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend();
1648 req->backupId = ptr.p->backupId;
1649 req->backupPtr = ptr.i;
1652 * We use trigger Ids that are unique to BACKUP.
1653 * These don't interfere with other triggers (e.g. from DBDICT)
1654 * as there is a special case in DBTUP.
1656 * Consequently, backups during online upgrade won't work
1658 ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
1659 ptr.p->masterData.sendCounter = ptr.p->nodes;
1660 NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1661 sendSignal(rg, GSN_START_BACKUP_REQ, signal,
1662 StartBackupReq::SignalLength, JBB);
1665 void
1666 Backup::execSTART_BACKUP_REF(Signal* signal)
1668 jamEntry();
1670 StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr();
1671 const Uint32 ptrI = ref->backupPtr;
1672 //const Uint32 backupId = ref->backupId;
1673 const Uint32 nodeId = ref->nodeId;
1675 BackupRecordPtr ptr LINT_SET_PTR;
1676 c_backupPool.getPtr(ptr, ptrI);
1678 ptr.p->setErrorCode(ref->errorCode);
1679 startBackupReply(signal, ptr, nodeId);
1682 void
1683 Backup::execSTART_BACKUP_CONF(Signal* signal)
1685 jamEntry();
1687 StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr();
1688 const Uint32 ptrI = conf->backupPtr;
1689 //const Uint32 backupId = conf->backupId;
1690 const Uint32 nodeId = refToNode(signal->senderBlockRef());
1692 BackupRecordPtr ptr LINT_SET_PTR;
1693 c_backupPool.getPtr(ptr, ptrI);
1695 startBackupReply(signal, ptr, nodeId);
1698 void
1699 Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
1702 CRASH_INSERTION((10004));
1704 if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) {
1705 jam();
1706 return;
1709 if (ERROR_INSERTED(10026))
1711 ptr.p->errorCode = 326;
1714 if(ptr.p->checkError()){
1715 jam();
1716 masterAbort(signal, ptr);
1717 return;
1721 * Wait for GCP
1723 ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
1724 ptr.p->masterData.waitGCP.startBackup = true;
1726 WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend();
1727 waitGCPReq->senderRef = reference();
1728 waitGCPReq->senderData = ptr.i;
1729 waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
1730 sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1731 WaitGCPReq::SignalLength,JBB);
1734 void
1735 Backup::execWAIT_GCP_REF(Signal* signal)
1737 jamEntry();
1739 CRASH_INSERTION((10006));
1741 WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr();
1742 const Uint32 ptrI = ref->senderData;
1744 BackupRecordPtr ptr LINT_SET_PTR;
1745 c_backupPool.getPtr(ptr, ptrI);
1747 ndbrequire(ptr.p->masterRef == reference());
1748 ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
1750 WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1751 req->senderRef = reference();
1752 req->senderData = ptr.i;
1753 req->requestType = WaitGCPReq::CompleteForceStart;
1754 sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1755 WaitGCPReq::SignalLength,JBB);
1758 void
1759 Backup::execWAIT_GCP_CONF(Signal* signal){
1760 jamEntry();
1762 CRASH_INSERTION((10007));
1764 WaitGCPConf * conf = (WaitGCPConf*)signal->getDataPtr();
1765 const Uint32 ptrI = conf->senderData;
1766 const Uint32 gcp = conf->gcp;
1768 BackupRecordPtr ptr LINT_SET_PTR;
1769 c_backupPool.getPtr(ptr, ptrI);
1771 ndbrequire(ptr.p->masterRef == reference());
1772 ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
1774 if(ptr.p->checkError()) {
1775 jam();
1776 masterAbort(signal, ptr);
1777 return;
1778 }//if
1780 if(ptr.p->masterData.waitGCP.startBackup) {
1781 jam();
1782 CRASH_INSERTION((10008));
1783 ptr.p->startGCP = gcp;
1784 ptr.p->masterData.sendCounter= 0;
1785 ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ;
1786 nextFragment(signal, ptr);
1787 return;
1788 } else {
1789 jam();
1790 if(gcp >= ptr.p->startGCP + 3)
1792 CRASH_INSERTION((10009));
1793 ptr.p->stopGCP = gcp;
1795 * Backup is complete - begin cleanup
1796 * STOP_BACKUP_REQ is sent to participants.
1797 * They then drop the local triggers
1799 sendStopBackup(signal, ptr);
1800 return;
1801 }//if
1804 * Make sure that we got entire stopGCP
1806 WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1807 req->senderRef = reference();
1808 req->senderData = ptr.i;
1809 req->requestType = WaitGCPReq::CompleteForceStart;
1810 sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1811 WaitGCPReq::SignalLength,JBB);
1812 return;
1816 /*****************************************************************************
1818 * Master functionallity - Backup fragment
1820 *****************************************************************************/
1821 void
1822 Backup::nextFragment(Signal* signal, BackupRecordPtr ptr)
1824 jam();
1826 BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtrSend();
1827 req->backupPtr = ptr.i;
1828 req->backupId = ptr.p->backupId;
1830 NodeBitmask nodes = ptr.p->nodes;
1831 Uint32 idleNodes = nodes.count();
1832 Uint32 saveIdleNodes = idleNodes;
1833 ndbrequire(idleNodes > 0);
1835 TablePtr tabPtr;
1836 ptr.p->tables.first(tabPtr);
1837 for(; tabPtr.i != RNIL && idleNodes > 0; ptr.p->tables.next(tabPtr)) {
1838 jam();
1839 FragmentPtr fragPtr;
1840 Array<Fragment> & frags = tabPtr.p->fragments;
1841 const Uint32 fragCount = frags.getSize();
1843 for(Uint32 i = 0; i<fragCount && idleNodes > 0; i++) {
1844 jam();
1845 tabPtr.p->fragments.getPtr(fragPtr, i);
1846 const Uint32 nodeId = fragPtr.p->node;
1847 if(fragPtr.p->scanning != 0) {
1848 jam();
1849 ndbrequire(nodes.get(nodeId));
1850 nodes.clear(nodeId);
1851 idleNodes--;
1852 } else if(fragPtr.p->scanned == 0 && nodes.get(nodeId)){
1853 jam();
1854 fragPtr.p->scanning = 1;
1855 nodes.clear(nodeId);
1856 idleNodes--;
1858 req->tableId = tabPtr.p->tableId;
1859 req->fragmentNo = i;
1860 req->count = 0;
1862 ptr.p->masterData.sendCounter++;
1863 const BlockReference ref = numberToRef(BACKUP, nodeId);
1864 sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal,
1865 BackupFragmentReq::SignalLength, JBB);
1866 }//if
1867 }//for
1868 }//for
1870 if(idleNodes != saveIdleNodes){
1871 jam();
1872 return;
1873 }//if
1876 * Finished with all tables
1879 ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
1880 ptr.p->masterData.waitGCP.startBackup = false;
1882 WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
1883 req->senderRef = reference();
1884 req->senderData = ptr.i;
1885 req->requestType = WaitGCPReq::CompleteForceStart;
1886 sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
1887 WaitGCPReq::SignalLength, JBB);
1891 void
1892 Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
1894 jamEntry();
1896 CRASH_INSERTION((10010));
1898 BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtr();
1899 const Uint32 ptrI = conf->backupPtr;
1900 //const Uint32 backupId = conf->backupId;
1901 const Uint32 tableId = conf->tableId;
1902 const Uint32 fragmentNo = conf->fragmentNo;
1903 const Uint32 nodeId = refToNode(signal->senderBlockRef());
1904 const Uint64 noOfBytes =
1905 conf->noOfBytesLow + (((Uint64)conf->noOfBytesHigh) << 32);
1906 const Uint64 noOfRecords =
1907 conf->noOfRecordsLow + (((Uint64)conf->noOfRecordsHigh) << 32);
1909 BackupRecordPtr ptr LINT_SET_PTR;
1910 c_backupPool.getPtr(ptr, ptrI);
1912 ptr.p->noOfBytes += noOfBytes;
1913 ptr.p->noOfRecords += noOfRecords;
1914 ptr.p->masterData.sendCounter--;
1916 TablePtr tabPtr;
1917 ndbrequire(findTable(ptr, tabPtr, tableId));
1919 tabPtr.p->noOfRecords += noOfRecords;
1921 FragmentPtr fragPtr;
1922 tabPtr.p->fragments.getPtr(fragPtr, fragmentNo);
1924 fragPtr.p->noOfRecords = noOfRecords;
1926 ndbrequire(fragPtr.p->scanned == 0);
1927 ndbrequire(fragPtr.p->scanning == 1);
1928 ndbrequire(fragPtr.p->node == nodeId);
1930 fragPtr.p->scanned = 1;
1931 fragPtr.p->scanning = 0;
1933 if (ERROR_INSERTED(10028))
1935 ptr.p->errorCode = 328;
1938 if(ptr.p->checkError())
1940 if(ptr.p->masterData.sendCounter.done())
1942 jam();
1943 masterAbort(signal, ptr);
1944 return;
1945 }//if
1947 else
1949 NodeBitmask nodes = ptr.p->nodes;
1950 nodes.clear(getOwnNodeId());
1951 if (!nodes.isclear())
1953 BackupFragmentCompleteRep *rep =
1954 (BackupFragmentCompleteRep*)signal->getDataPtrSend();
1955 rep->backupId = ptr.p->backupId;
1956 rep->backupPtr = ptr.i;
1957 rep->tableId = tableId;
1958 rep->fragmentNo = fragmentNo;
1959 rep->noOfTableRowsLow = (Uint32)(tabPtr.p->noOfRecords & 0xFFFFFFFF);
1960 rep->noOfTableRowsHigh = (Uint32)(tabPtr.p->noOfRecords >> 32);
1961 rep->noOfFragmentRowsLow = (Uint32)(noOfRecords & 0xFFFFFFFF);
1962 rep->noOfFragmentRowsHigh = (Uint32)(noOfRecords >> 32);
1963 NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
1964 sendSignal(rg, GSN_BACKUP_FRAGMENT_COMPLETE_REP, signal,
1965 BackupFragmentCompleteRep::SignalLength, JBB);
1967 nextFragment(signal, ptr);
1971 void
1972 Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
1974 jamEntry();
1976 CRASH_INSERTION((10011));
1978 BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
1979 const Uint32 ptrI = ref->backupPtr;
1980 //const Uint32 backupId = ref->backupId;
1981 const Uint32 nodeId = ref->nodeId;
1983 BackupRecordPtr ptr LINT_SET_PTR;
1984 c_backupPool.getPtr(ptr, ptrI);
1986 TablePtr tabPtr;
1987 ptr.p->tables.first(tabPtr);
1988 for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
1989 jam();
1990 FragmentPtr fragPtr;
1991 Array<Fragment> & frags = tabPtr.p->fragments;
1992 const Uint32 fragCount = frags.getSize();
1994 for(Uint32 i = 0; i<fragCount; i++) {
1995 jam();
1996 tabPtr.p->fragments.getPtr(fragPtr, i);
1997 if(fragPtr.p->scanning != 0 && nodeId == fragPtr.p->node)
1999 jam();
2000 ndbrequire(fragPtr.p->scanned == 0);
2001 fragPtr.p->scanned = 1;
2002 fragPtr.p->scanning = 0;
2003 goto done;
2007 goto err;
2009 done:
2010 ptr.p->masterData.sendCounter--;
2011 ptr.p->setErrorCode(ref->errorCode);
2013 if(ptr.p->masterData.sendCounter.done())
2015 jam();
2016 masterAbort(signal, ptr);
2017 return;
2018 }//if
2020 err:
2021 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2022 ord->backupId = ptr.p->backupId;
2023 ord->backupPtr = ptr.i;
2024 ord->requestType = AbortBackupOrd::LogBufferFull;
2025 ord->senderData= ptr.i;
2026 execABORT_BACKUP_ORD(signal);
2029 void
2030 Backup::execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal)
2032 jamEntry();
2033 BackupFragmentCompleteRep * rep =
2034 (BackupFragmentCompleteRep*)signal->getDataPtr();
2036 BackupRecordPtr ptr LINT_SET_PTR;
2037 c_backupPool.getPtr(ptr, rep->backupPtr);
2039 TablePtr tabPtr;
2040 ndbrequire(findTable(ptr, tabPtr, rep->tableId));
2042 tabPtr.p->noOfRecords =
2043 rep->noOfTableRowsLow + (((Uint64)rep->noOfTableRowsHigh) << 32);
2045 FragmentPtr fragPtr;
2046 tabPtr.p->fragments.getPtr(fragPtr, rep->fragmentNo);
2048 fragPtr.p->noOfRecords =
2049 rep->noOfFragmentRowsLow + (((Uint64)rep->noOfFragmentRowsHigh) << 32);
2052 /*****************************************************************************
2054 * Slave functionallity - Drop triggers
2056 *****************************************************************************/
2058 void
2059 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr)
2061 TablePtr tabPtr;
2062 ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
2064 if (ptr.p->slaveData.dropTrig.tableId == RNIL) {
2065 jam();
2066 if(ptr.p->tables.count())
2067 ptr.p->tables.first(tabPtr);
2068 else
2070 // Early abort, go to close files
2071 jam();
2072 closeFiles(signal, ptr);
2073 return;
2075 } else {
2076 jam();
2077 ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.dropTrig.tableId));
2078 ptr.p->tables.next(tabPtr);
2079 }//if
2080 if (tabPtr.i != RNIL) {
2081 jam();
2082 sendDropTrig(signal, ptr, tabPtr);
2083 } else {
2085 * Insert footers
2087 //if backup error, we needn't insert footers
2088 if(ptr.p->checkError())
2090 jam();
2091 closeFiles(signal, ptr);
2092 ptr.p->errorCode = 0;
2093 return;
2097 BackupFilePtr filePtr LINT_SET_PTR;
2098 ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
2099 Uint32 * dst;
2100 LINT_INIT(dst);
2101 ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
2102 * dst = 0;
2103 filePtr.p->operation.dataBuffer.updateWritePtr(1);
2107 BackupFilePtr filePtr LINT_SET_PTR;
2108 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2110 const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
2112 Uint32 * dst;
2113 LINT_INIT(dst);
2114 ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
2116 BackupFormat::CtlFile::GCPEntry * gcp =
2117 (BackupFormat::CtlFile::GCPEntry*)dst;
2119 gcp->SectionType = htonl(BackupFormat::GCP_ENTRY);
2120 gcp->SectionLength = htonl(gcpSz);
2121 gcp->StartGCP = htonl(ptr.p->startGCP);
2122 gcp->StopGCP = htonl(ptr.p->stopGCP - 1);
2123 filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
2126 TablePtr tabPtr;
2127 if (ptr.p->tables.first(tabPtr))
2129 jam();
2130 signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
2131 signal->theData[1] = ptr.i;
2132 signal->theData[2] = tabPtr.i;
2133 signal->theData[3] = 0;
2134 sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
2136 else
2138 jam();
2139 closeFiles(signal, ptr);
2146 void
2147 Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
2149 jam();
2150 DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend();
2152 ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
2153 ptr.p->slaveData.trigSendCounter = 0;
2154 req->setConnectionPtr(ptr.i);
2155 req->setUserRef(reference()); // Sending to myself
2156 req->setRequestType(DropTrigReq::RT_USER);
2157 req->setIndexId(RNIL);
2158 req->setTriggerInfo(0); // not used on DROP
2159 req->setTriggerType(TriggerType::SUBSCRIPTION);
2160 req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
2162 ptr.p->slaveData.dropTrig.tableId = tabPtr.p->tableId;
2163 req->setTableId(tabPtr.p->tableId);
2165 for (int i = 0; i < 3; i++) {
2166 Uint32 id = tabPtr.p->triggerIds[i];
2167 req->setTriggerId(id);
2168 req->setTriggerEvent(triggerEventValues[i]);
2169 sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
2170 signal, DropTrigReq::SignalLength, JBB);
2171 ptr.p->slaveData.trigSendCounter ++;
2175 void
2176 Backup::execDROP_TRIG_REF(Signal* signal)
2178 jamEntry();
2180 DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
2181 const Uint32 ptrI = ref->getConnectionPtr();
2183 BackupRecordPtr ptr LINT_SET_PTR;
2184 c_backupPool.getPtr(ptr, ptrI);
2186 if(ref->getConf()->getTriggerId() != ~(Uint32) 0)
2188 ndbout << "ERROR DROPPING TRIGGER: " << ref->getConf()->getTriggerId();
2189 ndbout << " Err: " << (Uint32)ref->getErrorCode() << endl << endl;
2192 dropTrigReply(signal, ptr);
2195 void
2196 Backup::execDROP_TRIG_CONF(Signal* signal)
2198 jamEntry();
2200 DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
2201 const Uint32 ptrI = conf->getConnectionPtr();
2203 BackupRecordPtr ptr LINT_SET_PTR;
2204 c_backupPool.getPtr(ptr, ptrI);
2206 dropTrigReply(signal, ptr);
2209 void
2210 Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr)
2212 CRASH_INSERTION((10012));
2214 ndbrequire(ptr.p->slaveData.gsn == GSN_DROP_TRIG_REQ);
2215 ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
2217 // move from .masterData to .slaveData
2218 ptr.p->slaveData.trigSendCounter--;
2219 if(ptr.p->slaveData.trigSendCounter.done() == false){
2220 jam();
2221 return;
2222 }//if
2224 sendDropTrig(signal, ptr); // recursive next
2227 /*****************************************************************************
2229 * Master functionallity - Stop backup
2231 *****************************************************************************/
2232 void
2233 Backup::execSTOP_BACKUP_REF(Signal* signal)
2235 jamEntry();
2237 StopBackupRef* ref = (StopBackupRef*)signal->getDataPtr();
2238 const Uint32 ptrI = ref->backupPtr;
2239 //const Uint32 backupId = ref->backupId;
2240 const Uint32 nodeId = ref->nodeId;
2242 BackupRecordPtr ptr LINT_SET_PTR;
2243 c_backupPool.getPtr(ptr, ptrI);
2245 ptr.p->setErrorCode(ref->errorCode);
2246 stopBackupReply(signal, ptr, nodeId);
2249 void
2250 Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr)
2252 jam();
2254 StopBackupReq* stop = (StopBackupReq*)signal->getDataPtrSend();
2255 stop->backupPtr = ptr.i;
2256 stop->backupId = ptr.p->backupId;
2257 stop->startGCP = ptr.p->startGCP;
2258 stop->stopGCP = ptr.p->stopGCP;
2260 ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
2261 ptr.p->masterData.sendCounter = ptr.p->nodes;
2262 NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
2263 sendSignal(rg, GSN_STOP_BACKUP_REQ, signal,
2264 StopBackupReq::SignalLength, JBB);
2267 void
2268 Backup::execSTOP_BACKUP_CONF(Signal* signal)
2270 jamEntry();
2272 StopBackupConf* conf = (StopBackupConf*)signal->getDataPtr();
2273 const Uint32 ptrI = conf->backupPtr;
2274 //const Uint32 backupId = conf->backupId;
2275 const Uint32 nodeId = refToNode(signal->senderBlockRef());
2277 BackupRecordPtr ptr LINT_SET_PTR;
2278 c_backupPool.getPtr(ptr, ptrI);
2280 ptr.p->noOfLogBytes += conf->noOfLogBytes;
2281 ptr.p->noOfLogRecords += conf->noOfLogRecords;
2283 stopBackupReply(signal, ptr, nodeId);
2286 void
2287 Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
2289 CRASH_INSERTION((10013));
2291 if (!haveAllSignals(ptr, GSN_STOP_BACKUP_REQ, nodeId)) {
2292 jam();
2293 return;
2296 sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete);
2298 if(!ptr.p->checkError())
2300 if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
2302 BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
2303 rep->backupId = ptr.p->backupId;
2304 rep->senderData = ptr.p->clientData;
2305 rep->startGCP = ptr.p->startGCP;
2306 rep->stopGCP = ptr.p->stopGCP;
2307 rep->noOfBytesLow = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
2308 rep->noOfRecordsLow = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
2309 rep->noOfBytesHigh = (Uint32)(ptr.p->noOfBytes >> 32);
2310 rep->noOfRecordsHigh = (Uint32)(ptr.p->noOfRecords >> 32);
2311 rep->noOfLogBytes = ptr.p->noOfLogBytes;
2312 rep->noOfLogRecords = ptr.p->noOfLogRecords;
2313 rep->nodes = ptr.p->nodes;
2314 sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
2315 BackupCompleteRep::SignalLength, JBB);
2318 signal->theData[0] = NDB_LE_BackupCompleted;
2319 signal->theData[1] = ptr.p->clientRef;
2320 signal->theData[2] = ptr.p->backupId;
2321 signal->theData[3] = ptr.p->startGCP;
2322 signal->theData[4] = ptr.p->stopGCP;
2323 signal->theData[5] = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
2324 signal->theData[6] = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
2325 signal->theData[7] = ptr.p->noOfLogBytes;
2326 signal->theData[8] = ptr.p->noOfLogRecords;
2327 ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9);
2328 signal->theData[9+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfBytes >> 32);
2329 signal->theData[10+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfRecords >> 32);
2330 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 11+NdbNodeBitmask::Size, JBB);
2332 else
2334 masterAbort(signal, ptr);
2338 /*****************************************************************************
2340 * Master functionallity - Abort backup
2342 *****************************************************************************/
2343 void
2344 Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
2346 jam();
2347 #ifdef DEBUG_ABORT
2348 ndbout_c("************ masterAbort");
2349 #endif
2351 ndbassert(ptr.p->masterRef == reference());
2353 if(ptr.p->masterData.errorCode != 0)
2355 jam();
2356 return;
2359 if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
2361 BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
2362 rep->backupId = ptr.p->backupId;
2363 rep->senderData = ptr.p->clientData;
2364 rep->reason = ptr.p->errorCode;
2365 sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
2366 BackupAbortRep::SignalLength, JBB);
2368 signal->theData[0] = NDB_LE_BackupAborted;
2369 signal->theData[1] = ptr.p->clientRef;
2370 signal->theData[2] = ptr.p->backupId;
2371 signal->theData[3] = ptr.p->errorCode;
2372 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
2374 ndbrequire(ptr.p->errorCode);
2375 ptr.p->masterData.errorCode = ptr.p->errorCode;
2377 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2378 ord->backupId = ptr.p->backupId;
2379 ord->backupPtr = ptr.i;
2380 ord->senderData= ptr.i;
2381 NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
2383 switch(ptr.p->masterData.gsn){
2384 case GSN_DEFINE_BACKUP_REQ:
2385 ord->requestType = AbortBackupOrd::BackupFailure;
2386 sendSignal(rg, GSN_ABORT_BACKUP_ORD, signal,
2387 AbortBackupOrd::SignalLength, JBB);
2388 return;
2389 case GSN_CREATE_TRIG_REQ:
2390 case GSN_START_BACKUP_REQ:
2391 case GSN_ALTER_TRIG_REQ:
2392 case GSN_WAIT_GCP_REQ:
2393 case GSN_BACKUP_FRAGMENT_REQ:
2394 jam();
2395 ptr.p->stopGCP= ptr.p->startGCP + 1;
2396 sendStopBackup(signal, ptr); // dropping due to error
2397 return;
2398 case GSN_UTIL_SEQUENCE_REQ:
2399 case GSN_UTIL_LOCK_REQ:
2400 ndbrequire(false);
2401 return;
2402 case GSN_DROP_TRIG_REQ:
2403 case GSN_STOP_BACKUP_REQ:
2404 return;
2408 void
2409 Backup::abort_scan(Signal * signal, BackupRecordPtr ptr)
2411 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
2412 ord->backupId = ptr.p->backupId;
2413 ord->backupPtr = ptr.i;
2414 ord->senderData= ptr.i;
2415 ord->requestType = AbortBackupOrd::AbortScan;
2417 TablePtr tabPtr;
2418 ptr.p->tables.first(tabPtr);
2419 for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
2420 jam();
2421 FragmentPtr fragPtr;
2422 Array<Fragment> & frags = tabPtr.p->fragments;
2423 const Uint32 fragCount = frags.getSize();
2425 for(Uint32 i = 0; i<fragCount; i++) {
2426 jam();
2427 tabPtr.p->fragments.getPtr(fragPtr, i);
2428 const Uint32 nodeId = fragPtr.p->node;
2429 if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) {
2430 jam();
2432 const BlockReference ref = numberToRef(BACKUP, nodeId);
2433 sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal,
2434 AbortBackupOrd::SignalLength, JBB);
2441 /*****************************************************************************
2443 * Slave functionallity: Define Backup
2445 *****************************************************************************/
2446 void
2447 Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode)
2449 jam();
2450 ptr.p->setErrorCode(errCode);
2451 if(ptr.p->is_lcp())
2453 jam();
2454 if (ptr.p->ctlFilePtr == RNIL) {
2455 ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
2456 ndbrequire(ptr.p->errorCode != 0);
2457 DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
2458 ref->backupId = ptr.p->backupId;
2459 ref->backupPtr = ptr.i;
2460 ref->errorCode = ptr.p->errorCode;
2461 ref->nodeId = getOwnNodeId();
2462 sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
2463 DefineBackupRef::SignalLength, JBB);
2464 return;
2467 BackupFilePtr filePtr LINT_SET_PTR;
2468 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2469 if (filePtr.p->m_flags & BackupFile::BF_LCP_META)
2471 jam();
2472 ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD));
2473 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
2474 if (filePtr.p->m_flags & BackupFile::BF_OPEN)
2476 closeFile(signal, ptr, filePtr);
2477 return;
2481 ndbrequire(filePtr.p->m_flags == 0);
2483 TablePtr tabPtr;
2484 FragmentPtr fragPtr;
2486 ndbrequire(ptr.p->tables.first(tabPtr));
2487 tabPtr.p->fragments.getPtr(fragPtr, 0);
2489 LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtrSend();
2490 ref->senderData = ptr.p->clientData;
2491 ref->senderRef = reference();
2492 ref->tableId = tabPtr.p->tableId;
2493 ref->fragmentId = fragPtr.p->fragmentId;
2494 ref->errorCode = errCode;
2495 sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_REF,
2496 signal, LcpPrepareRef::SignalLength, JBB);
2497 return;
2500 ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
2501 ndbrequire(ptr.p->errorCode != 0);
2503 DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
2504 ref->backupId = ptr.p->backupId;
2505 ref->backupPtr = ptr.i;
2506 ref->errorCode = ptr.p->errorCode;
2507 ref->nodeId = getOwnNodeId();
2508 sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
2509 DefineBackupRef::SignalLength, JBB);
2512 void
2513 Backup::execDEFINE_BACKUP_REQ(Signal* signal)
2515 jamEntry();
2517 DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr();
2519 BackupRecordPtr ptr LINT_SET_PTR;
2520 const Uint32 ptrI = req->backupPtr;
2521 const Uint32 backupId = req->backupId;
2522 const BlockReference senderRef = req->senderRef;
2524 if(senderRef == reference()){
2526 * Signal sent from myself -> record already seized
2528 jam();
2529 c_backupPool.getPtr(ptr, ptrI);
2530 } else { // from other node
2531 jam();
2532 #ifdef DEBUG_ABORT
2533 dumpUsedResources();
2534 #endif
2535 if(!c_backups.seizeId(ptr, ptrI)) {
2536 jam();
2537 ndbrequire(false); // If master has succeeded slave should succed
2538 }//if
2539 }//if
2541 CRASH_INSERTION((10014));
2543 ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ;
2544 ptr.p->slaveState.forceState(INITIAL);
2545 ptr.p->slaveState.setState(DEFINING);
2546 ptr.p->slaveData.dropTrig.tableId = RNIL;
2547 ptr.p->errorCode = 0;
2548 ptr.p->clientRef = req->clientRef;
2549 ptr.p->clientData = req->clientData;
2550 if(senderRef == reference())
2551 ptr.p->flags = req->flags;
2552 else
2553 ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
2554 * as non master should never
2555 * reply
2557 ptr.p->masterRef = senderRef;
2558 ptr.p->nodes = req->nodes;
2559 ptr.p->backupId = backupId;
2560 ptr.p->backupKey[0] = req->backupKey[0];
2561 ptr.p->backupKey[1] = req->backupKey[1];
2562 ptr.p->backupDataLen = req->backupDataLen;
2563 ptr.p->masterData.errorCode = 0;
2564 ptr.p->noOfBytes = 0;
2565 ptr.p->noOfRecords = 0;
2566 ptr.p->noOfLogBytes = 0;
2567 ptr.p->noOfLogRecords = 0;
2568 ptr.p->currGCP = 0;
2569 ptr.p->startGCP = 0;
2570 ptr.p->stopGCP = 0;
2573 * Allocate files
2575 BackupFilePtr files[3];
2576 Uint32 noOfPages[] = {
2577 NO_OF_PAGES_META_FILE,
2578 2, // 32k
2579 0 // 3M
2581 const Uint32 maxInsert[] = {
2582 MAX_WORDS_META_FILE,
2583 4096, // 16k
2584 16*3000, // Max 16 tuples
2586 Uint32 minWrite[] = {
2587 8192,
2588 8192,
2589 32768
2591 Uint32 maxWrite[] = {
2592 8192,
2593 8192,
2594 32768
2597 minWrite[1] = c_defaults.m_minWriteSize;
2598 maxWrite[1] = c_defaults.m_maxWriteSize;
2599 noOfPages[1] = (c_defaults.m_logBufferSize + sizeof(Page32) - 1) /
2600 sizeof(Page32);
2601 minWrite[2] = c_defaults.m_minWriteSize;
2602 maxWrite[2] = c_defaults.m_maxWriteSize;
2603 noOfPages[2] = (c_defaults.m_dataBufferSize + sizeof(Page32) - 1) /
2604 sizeof(Page32);
2606 if (ptr.p->is_lcp())
2608 noOfPages[2] = (c_defaults.m_lcp_buffer_size + sizeof(Page32) - 1) /
2609 sizeof(Page32);
2612 ptr.p->ctlFilePtr = ptr.p->logFilePtr = ptr.p->dataFilePtr = RNIL;
2614 for(Uint32 i = 0; i<3; i++) {
2615 jam();
2616 if(ptr.p->is_lcp() && i != 2)
2618 files[i].i = RNIL;
2619 continue;
2621 if(!ptr.p->files.seize(files[i])) {
2622 jam();
2623 defineBackupRef(signal, ptr,
2624 DefineBackupRef::FailedToAllocateFileRecord);
2625 return;
2626 }//if
2628 files[i].p->tableId = RNIL;
2629 files[i].p->backupPtr = ptr.i;
2630 files[i].p->filePointer = RNIL;
2631 files[i].p->m_flags = 0;
2632 files[i].p->errorCode = 0;
2634 if(ERROR_INSERTED(10035) || files[i].p->pages.seize(noOfPages[i]) == false)
2636 jam();
2637 DEBUG_OUT("Failed to seize " << noOfPages[i] << " pages");
2638 defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateBuffers);
2639 return;
2640 }//if
2641 Page32Ptr pagePtr;
2642 files[i].p->pages.getPtr(pagePtr, 0);
2644 const char * msg = files[i].p->
2645 operation.dataBuffer.setup((Uint32*)pagePtr.p,
2646 noOfPages[i] * (sizeof(Page32) >> 2),
2647 128,
2648 minWrite[i] >> 2,
2649 maxWrite[i] >> 2,
2650 maxInsert[i]);
2651 if(msg != 0) {
2652 jam();
2653 defineBackupRef(signal, ptr, DefineBackupRef::FailedToSetupFsBuffers);
2654 return;
2655 }//if
2657 switch(i){
2658 case 0:
2659 files[i].p->fileType = BackupFormat::CTL_FILE;
2660 ptr.p->ctlFilePtr = files[i].i;
2661 break;
2662 case 1:
2663 files[i].p->fileType = BackupFormat::LOG_FILE;
2664 ptr.p->logFilePtr = files[i].i;
2665 break;
2666 case 2:
2667 files[i].p->fileType = BackupFormat::DATA_FILE;
2668 ptr.p->dataFilePtr = files[i].i;
2670 }//for
2672 if (!verifyNodesAlive(ptr, ptr.p->nodes)) {
2673 jam();
2674 defineBackupRef(signal, ptr, DefineBackupRef::Undefined);
2675 return;
2676 }//if
2677 if (ERROR_INSERTED(10027)) {
2678 jam();
2679 defineBackupRef(signal, ptr, 327);
2680 return;
2681 }//if
2683 if(ptr.p->backupDataLen == 0) {
2684 jam();
2685 backupAllData(signal, ptr);
2686 return;
2687 }//if
2689 if(ptr.p->is_lcp())
2691 jam();
2692 getFragmentInfoDone(signal, ptr);
2693 return;
2697 * Not implemented
2699 ndbrequire(0);
2702 void
2703 Backup::backupAllData(Signal* signal, BackupRecordPtr ptr)
2706 * Get all tables from dict
2708 ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend();
2709 req->senderRef = reference();
2710 req->senderData = ptr.i;
2711 req->requestData = 0;
2712 sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal,
2713 ListTablesReq::SignalLength, JBB);
2716 void
2717 Backup::execLIST_TABLES_CONF(Signal* signal)
2719 jamEntry();
2721 ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr();
2723 BackupRecordPtr ptr LINT_SET_PTR;
2724 c_backupPool.getPtr(ptr, conf->senderData);
2726 const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
2727 for(unsigned int i = 0; i<len; i++) {
2728 jam();
2729 Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
2730 Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
2731 Uint32 state= ListTablesConf::getTableState(conf->tableData[i]);
2733 if (! (DictTabInfo::isTable(tableType) ||
2734 DictTabInfo::isIndex(tableType) ||
2735 DictTabInfo::isFilegroup(tableType) ||
2736 DictTabInfo::isFile(tableType)))
2738 jam();
2739 continue;
2742 if (state != DictTabInfo::StateOnline)
2744 jam();
2745 continue;
2748 TablePtr tabPtr;
2749 ptr.p->tables.seize(tabPtr);
2750 if(tabPtr.i == RNIL) {
2751 jam();
2752 defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateTables);
2753 return;
2754 }//if
2755 tabPtr.p->tableId = tableId;
2756 tabPtr.p->tableType = tableType;
2757 }//for
2759 if(len == ListTablesConf::DataLength) {
2760 jam();
2762 * Not finished...
2764 return;
2765 }//if
2768 * All tables fetched
2770 openFiles(signal, ptr);
2773 void
2774 Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
2776 jam();
2778 BackupFilePtr filePtr LINT_SET_PTR;
2780 FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
2781 req->userReference = reference();
2782 req->fileFlags =
2783 FsOpenReq::OM_WRITEONLY |
2784 FsOpenReq::OM_TRUNCATE |
2785 FsOpenReq::OM_CREATE |
2786 FsOpenReq::OM_APPEND |
2787 FsOpenReq::OM_AUTOSYNC;
2788 FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
2789 req->auto_sync_size = c_defaults.m_disk_synch_size;
2791 * Ctl file
2793 c_backupFilePool.getPtr(filePtr, ptr.p->ctlFilePtr);
2794 filePtr.p->m_flags |= BackupFile::BF_OPENING;
2796 req->userPointer = filePtr.i;
2797 FsOpenReq::setVersion(req->fileNumber, 2);
2798 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
2799 FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2800 FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2801 sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2804 * Log file
2806 c_backupFilePool.getPtr(filePtr, ptr.p->logFilePtr);
2807 filePtr.p->m_flags |= BackupFile::BF_OPENING;
2809 req->userPointer = filePtr.i;
2810 FsOpenReq::setVersion(req->fileNumber, 2);
2811 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_LOG);
2812 FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2813 FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2814 sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2817 * Data file
2819 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
2820 filePtr.p->m_flags |= BackupFile::BF_OPENING;
2822 if (c_defaults.m_o_direct)
2823 req->fileFlags |= FsOpenReq::OM_DIRECT;
2824 req->userPointer = filePtr.i;
2825 FsOpenReq::setVersion(req->fileNumber, 2);
2826 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
2827 FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
2828 FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
2829 FsOpenReq::v2_setCount(req->fileNumber, 0);
2830 sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
2833 void
2834 Backup::execFSOPENREF(Signal* signal)
2836 jamEntry();
2838 FsRef * ref = (FsRef *)signal->getDataPtr();
2840 const Uint32 userPtr = ref->userPointer;
2842 BackupFilePtr filePtr LINT_SET_PTR;
2843 c_backupFilePool.getPtr(filePtr, userPtr);
2845 BackupRecordPtr ptr LINT_SET_PTR;
2846 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
2847 ptr.p->setErrorCode(ref->errorCode);
2848 openFilesReply(signal, ptr, filePtr);
2851 void
2852 Backup::execFSOPENCONF(Signal* signal)
2854 jamEntry();
2856 FsConf * conf = (FsConf *)signal->getDataPtr();
2858 const Uint32 userPtr = conf->userPointer;
2859 const Uint32 filePointer = conf->filePointer;
2861 BackupFilePtr filePtr LINT_SET_PTR;
2862 c_backupFilePool.getPtr(filePtr, userPtr);
2863 filePtr.p->filePointer = filePointer;
2865 BackupRecordPtr ptr LINT_SET_PTR;
2866 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
2868 ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPEN));
2869 filePtr.p->m_flags |= BackupFile::BF_OPEN;
2870 openFilesReply(signal, ptr, filePtr);
2873 void
2874 Backup::openFilesReply(Signal* signal,
2875 BackupRecordPtr ptr, BackupFilePtr filePtr)
2877 jam();
2880 * Mark files as "opened"
2882 ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPENING);
2883 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_OPENING;
2884 filePtr.p->m_flags |= BackupFile::BF_OPEN;
2886 * Check if all files have recived open_reply
2888 for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
2890 jam();
2891 if(filePtr.p->m_flags & BackupFile::BF_OPENING) {
2892 jam();
2893 return;
2894 }//if
2895 }//for
2898 * Did open succeed for all files
2900 if(ptr.p->checkError()) {
2901 jam();
2902 defineBackupRef(signal, ptr);
2903 return;
2904 }//if
2906 if(!ptr.p->is_lcp())
2909 * Insert file headers
2911 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2912 if(!insertFileHeader(BackupFormat::CTL_FILE, ptr.p, filePtr.p)) {
2913 jam();
2914 defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2915 return;
2916 }//if
2918 ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
2919 if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
2920 jam();
2921 defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2922 return;
2923 }//if
2925 ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
2926 if(!insertFileHeader(BackupFormat::DATA_FILE, ptr.p, filePtr.p)) {
2927 jam();
2928 defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2929 return;
2930 }//if
2932 else
2934 ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
2935 if(!insertFileHeader(BackupFormat::LCP_FILE, ptr.p, filePtr.p)) {
2936 jam();
2937 defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
2938 return;
2939 }//if
2941 ptr.p->ctlFilePtr = ptr.p->dataFilePtr;
2945 * Start CTL file thread
2947 if (!ptr.p->is_lcp())
2949 jam();
2950 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
2951 filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
2953 signal->theData[0] = BackupContinueB::START_FILE_THREAD;
2954 signal->theData[1] = filePtr.i;
2955 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
2957 else
2959 jam();
2960 filePtr.p->m_flags |= BackupFile::BF_LCP_META;
2964 * Insert table list in ctl file
2966 FsBuffer & buf = filePtr.p->operation.dataBuffer;
2968 const Uint32 sz =
2969 (sizeof(BackupFormat::CtlFile::TableList) >> 2) +
2970 ptr.p->tables.count() - 1;
2972 Uint32 * dst;
2973 ndbrequire(sz < buf.getMaxWrite());
2974 if(!buf.getWritePtr(&dst, sz)) {
2975 jam();
2976 defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertTableList);
2977 return;
2978 }//if
2980 BackupFormat::CtlFile::TableList* tl =
2981 (BackupFormat::CtlFile::TableList*)dst;
2982 tl->SectionType = htonl(BackupFormat::TABLE_LIST);
2983 tl->SectionLength = htonl(sz);
2985 TablePtr tabPtr;
2986 Uint32 count = 0;
2987 for(ptr.p->tables.first(tabPtr);
2988 tabPtr.i != RNIL;
2989 ptr.p->tables.next(tabPtr)){
2990 jam();
2991 tl->TableIds[count] = htonl(tabPtr.p->tableId);
2992 count++;
2993 }//for
2995 buf.updateWritePtr(sz);
2998 * Start getting table definition data
3000 ndbrequire(ptr.p->tables.first(tabPtr));
3002 signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
3003 signal->theData[1] = ptr.i;
3004 signal->theData[2] = tabPtr.i;
3005 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
3006 return;
3009 bool
3010 Backup::insertFileHeader(BackupFormat::FileType ft,
3011 BackupRecord * ptrP,
3012 BackupFile * filePtrP){
3013 FsBuffer & buf = filePtrP->operation.dataBuffer;
3015 const Uint32 sz = sizeof(BackupFormat::FileHeader) >> 2;
3017 Uint32 * dst;
3018 ndbrequire(sz < buf.getMaxWrite());
3019 if(!buf.getWritePtr(&dst, sz)) {
3020 jam();
3021 return false;
3022 }//if
3024 BackupFormat::FileHeader* header = (BackupFormat::FileHeader*)dst;
3025 ndbrequire(sizeof(header->Magic) == sizeof(BACKUP_MAGIC));
3026 memcpy(header->Magic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC));
3027 header->NdbVersion = htonl(NDB_VERSION);
3028 header->SectionType = htonl(BackupFormat::FILE_HEADER);
3029 header->SectionLength = htonl(sz - 3);
3030 header->FileType = htonl(ft);
3031 header->BackupId = htonl(ptrP->backupId);
3032 header->BackupKey_0 = htonl(ptrP->backupKey[0]);
3033 header->BackupKey_1 = htonl(ptrP->backupKey[1]);
3034 header->ByteOrder = 0x12345678;
3036 buf.updateWritePtr(sz);
3037 return true;
3040 void
3041 Backup::execGET_TABINFOREF(Signal* signal)
3043 GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr();
3045 const Uint32 senderData = ref->senderData;
3046 BackupRecordPtr ptr LINT_SET_PTR;
3047 c_backupPool.getPtr(ptr, senderData);
3049 BackupFilePtr filePtr LINT_SET_PTR;
3050 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
3051 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
3053 defineBackupRef(signal, ptr, ref->errorCode);
3056 void
3057 Backup::execGET_TABINFO_CONF(Signal* signal)
3059 jamEntry();
3061 if(!assembleFragments(signal)) {
3062 jam();
3063 return;
3064 }//if
3066 GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
3067 //const Uint32 senderRef = info->senderRef;
3068 const Uint32 len = conf->totalLen;
3069 const Uint32 senderData = conf->senderData;
3070 const Uint32 tableType = conf->tableType;
3071 const Uint32 tableId = conf->tableId;
3073 BackupRecordPtr ptr LINT_SET_PTR;
3074 c_backupPool.getPtr(ptr, senderData);
3076 SegmentedSectionPtr dictTabInfoPtr;
3077 signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
3078 ndbrequire(dictTabInfoPtr.sz == len);
3080 TablePtr tabPtr ;
3081 ndbrequire(findTable(ptr, tabPtr, tableId));
3083 BackupFilePtr filePtr LINT_SET_PTR;
3084 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
3085 FsBuffer & buf = filePtr.p->operation.dataBuffer;
3086 Uint32* dst = 0;
3087 { // Write into ctl file
3088 Uint32 dstLen = len + 3;
3089 if(!buf.getWritePtr(&dst, dstLen)) {
3090 jam();
3091 ndbrequire(false);
3092 ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
3093 releaseSections(signal);
3094 defineBackupRef(signal, ptr);
3095 return;
3096 }//if
3097 if(dst != 0) {
3098 jam();
3100 BackupFormat::CtlFile::TableDescription * desc =
3101 (BackupFormat::CtlFile::TableDescription*)dst;
3102 desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION);
3103 desc->SectionLength = htonl(len + 3);
3104 desc->TableType = htonl(tableType);
3105 dst += 3;
3107 copy(dst, dictTabInfoPtr);
3108 buf.updateWritePtr(dstLen);
3109 }//if
3112 releaseSections(signal);
3114 if(ptr.p->checkError()) {
3115 jam();
3116 defineBackupRef(signal, ptr);
3117 return;
3118 }//if
3120 if (!DictTabInfo::isTable(tabPtr.p->tableType))
3122 jam();
3124 TablePtr tmp = tabPtr;
3125 ptr.p->tables.next(tabPtr);
3126 ptr.p->tables.release(tmp);
3127 goto next;
3130 if (!parseTableDescription(signal, ptr, tabPtr, dst, len))
3132 jam();
3133 defineBackupRef(signal, ptr);
3134 return;
3137 if(!ptr.p->is_lcp())
3139 jam();
3140 signal->theData[0] = tabPtr.p->tableId;
3141 signal->theData[1] = 1; // lock
3142 EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
3145 ptr.p->tables.next(tabPtr);
3147 next:
3148 if(tabPtr.i == RNIL)
3151 * Done with all tables...
3153 jam();
3155 if(ptr.p->is_lcp())
3157 lcp_open_file_done(signal, ptr);
3158 return;
3161 ndbrequire(ptr.p->tables.first(tabPtr));
3162 DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
3163 req->m_connectionData = RNIL;
3164 req->m_tableRef = tabPtr.p->tableId;
3165 req->m_senderData = ptr.i;
3166 sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
3167 DihFragCountReq::SignalLength, JBB);
3168 return;
3169 }//if
3172 * Fetch next table...
3174 signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
3175 signal->theData[1] = ptr.i;
3176 signal->theData[2] = tabPtr.i;
3177 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
3178 return;
3181 bool
3182 Backup::parseTableDescription(Signal* signal,
3183 BackupRecordPtr ptr,
3184 TablePtr tabPtr,
3185 const Uint32 * tabdescptr,
3186 Uint32 len)
3188 SimplePropertiesLinearReader it(tabdescptr, len);
3190 it.first();
3192 DictTabInfo::Table tmpTab; tmpTab.init();
3193 SimpleProperties::UnpackStatus stat;
3194 stat = SimpleProperties::unpack(it, &tmpTab,
3195 DictTabInfo::TableMapping,
3196 DictTabInfo::TableMappingSize,
3197 true, true);
3198 ndbrequire(stat == SimpleProperties::Break);
3200 bool lcp = ptr.p->is_lcp();
3202 ndbrequire(tabPtr.p->tableId == tmpTab.TableId);
3203 ndbrequire(lcp || (tabPtr.p->tableType == tmpTab.TableType));
3206 * LCP should not save disk attributes but only mem attributes
3210 * Initialize table object
3212 tabPtr.p->noOfRecords = 0;
3213 tabPtr.p->schemaVersion = tmpTab.TableVersion;
3214 tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
3215 tabPtr.p->noOfNull = 0;
3216 tabPtr.p->noOfVariable = 0; // Computed while iterating over attribs
3217 tabPtr.p->sz_FixedAttributes = 0; // Computed while iterating over attribs
3218 tabPtr.p->triggerIds[0] = ILLEGAL_TRIGGER_ID;
3219 tabPtr.p->triggerIds[1] = ILLEGAL_TRIGGER_ID;
3220 tabPtr.p->triggerIds[2] = ILLEGAL_TRIGGER_ID;
3221 tabPtr.p->triggerAllocated[0] = false;
3222 tabPtr.p->triggerAllocated[1] = false;
3223 tabPtr.p->triggerAllocated[2] = false;
3225 Uint32 disk = 0;
3226 const Uint32 count = tabPtr.p->noOfAttributes;
3227 for(Uint32 i = 0; i<count; i++) {
3228 jam();
3229 DictTabInfo::Attribute tmp; tmp.init();
3230 stat = SimpleProperties::unpack(it, &tmp,
3231 DictTabInfo::AttributeMapping,
3232 DictTabInfo::AttributeMappingSize,
3233 true, true);
3235 ndbrequire(stat == SimpleProperties::Break);
3236 it.next(); // Move Past EndOfAttribute
3238 const Uint32 arr = tmp.AttributeArraySize;
3239 const Uint32 sz = 1 << tmp.AttributeSize;
3240 const Uint32 sz32 = (sz * arr + 31) >> 5;
3242 if(lcp && tmp.AttributeStorageType == NDB_STORAGETYPE_DISK)
3244 disk++;
3245 continue;
3248 AttributePtr attrPtr;
3249 if(!tabPtr.p->attributes.seize(attrPtr))
3251 jam();
3252 ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
3253 return false;
3256 attrPtr.p->data.m_flags = 0;
3257 attrPtr.p->data.attrId = tmp.AttributeId;
3259 attrPtr.p->data.m_flags |=
3260 (tmp.AttributeNullableFlag ? Attribute::COL_NULLABLE : 0);
3261 attrPtr.p->data.m_flags |= (tmp.AttributeArrayType == NDB_ARRAYTYPE_FIXED)?
3262 Attribute::COL_FIXED : 0;
3263 attrPtr.p->data.sz32 = sz32;
3266 * 1) Fixed non-nullable
3267 * 2) Other
3269 if(attrPtr.p->data.m_flags & Attribute::COL_FIXED &&
3270 !(attrPtr.p->data.m_flags & Attribute::COL_NULLABLE)) {
3271 jam();
3272 attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3273 tabPtr.p->sz_FixedAttributes += sz32;
3274 } else {
3275 attrPtr.p->data.offset = ~0;
3276 tabPtr.p->noOfVariable++;
3278 }//for
3281 if(lcp)
3283 if (disk)
3286 * Remove all disk attributes
3288 tabPtr.p->noOfAttributes -= disk;
3291 AttributePtr attrPtr;
3292 ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3294 Uint32 sz32 = 2;
3295 attrPtr.p->data.attrId = AttributeHeader::DISK_REF;
3296 attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3297 attrPtr.p->data.sz32 = 2;
3299 attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3300 tabPtr.p->sz_FixedAttributes += sz32;
3301 tabPtr.p->noOfAttributes ++;
3306 AttributePtr attrPtr;
3307 ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3309 Uint32 sz32 = 2;
3310 attrPtr.p->data.attrId = AttributeHeader::ROWID;
3311 attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3312 attrPtr.p->data.sz32 = 2;
3314 attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3315 tabPtr.p->sz_FixedAttributes += sz32;
3316 tabPtr.p->noOfAttributes ++;
3319 if (tmpTab.RowGCIFlag)
3321 AttributePtr attrPtr;
3322 ndbrequire(tabPtr.p->attributes.seize(attrPtr));
3324 Uint32 sz32 = 2;
3325 attrPtr.p->data.attrId = AttributeHeader::ROW_GCI;
3326 attrPtr.p->data.m_flags = Attribute::COL_FIXED;
3327 attrPtr.p->data.sz32 = 2;
3329 attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
3330 tabPtr.p->sz_FixedAttributes += sz32;
3331 tabPtr.p->noOfAttributes ++;
3334 return true;
3337 void
3338 Backup::execDI_FCOUNTCONF(Signal* signal)
3340 jamEntry();
3341 DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
3342 const Uint32 userPtr = conf->m_connectionData;
3343 const Uint32 fragCount = conf->m_fragmentCount;
3344 const Uint32 tableId = conf->m_tableRef;
3345 const Uint32 senderData = conf->m_senderData;
3347 ndbrequire(userPtr == RNIL && signal->length() == 5);
3349 BackupRecordPtr ptr LINT_SET_PTR;
3350 c_backupPool.getPtr(ptr, senderData);
3352 TablePtr tabPtr;
3353 ndbrequire(findTable(ptr, tabPtr, tableId));
3355 ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
3356 for(Uint32 i = 0; i<fragCount; i++) {
3357 jam();
3358 FragmentPtr fragPtr;
3359 tabPtr.p->fragments.getPtr(fragPtr, i);
3360 fragPtr.p->scanned = 0;
3361 fragPtr.p->scanning = 0;
3362 fragPtr.p->tableId = tableId;
3363 fragPtr.p->fragmentId = i;
3364 fragPtr.p->node = 0;
3365 }//for
3368 * Next table
3370 if(ptr.p->tables.next(tabPtr)) {
3371 jam();
3372 DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
3373 req->m_connectionData = RNIL;
3374 req->m_tableRef = tabPtr.p->tableId;
3375 req->m_senderData = ptr.i;
3376 sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
3377 DihFragCountReq::SignalLength, JBB);
3378 return;
3379 }//if
3381 ptr.p->tables.first(tabPtr);
3382 getFragmentInfo(signal, ptr, tabPtr, 0);
3385 void
3386 Backup::getFragmentInfo(Signal* signal,
3387 BackupRecordPtr ptr, TablePtr tabPtr, Uint32 fragNo)
3389 jam();
3391 for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
3392 jam();
3393 const Uint32 fragCount = tabPtr.p->fragments.getSize();
3394 for(; fragNo < fragCount; fragNo ++) {
3395 jam();
3396 FragmentPtr fragPtr;
3397 tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3399 if(fragPtr.p->scanned == 0 && fragPtr.p->scanning == 0) {
3400 jam();
3401 signal->theData[0] = RNIL;
3402 signal->theData[1] = ptr.i;
3403 signal->theData[2] = tabPtr.p->tableId;
3404 signal->theData[3] = fragNo;
3405 sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
3406 return;
3407 }//if
3408 }//for
3409 fragNo = 0;
3410 }//for
3412 getFragmentInfoDone(signal, ptr);
3415 void
3416 Backup::execDIGETPRIMCONF(Signal* signal)
3418 jamEntry();
3420 const Uint32 userPtr = signal->theData[0];
3421 const Uint32 senderData = signal->theData[1];
3422 const Uint32 nodeCount = signal->theData[6];
3423 const Uint32 tableId = signal->theData[7];
3424 const Uint32 fragNo = signal->theData[8];
3426 ndbrequire(userPtr == RNIL && signal->length() == 9);
3427 ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
3429 BackupRecordPtr ptr LINT_SET_PTR;
3430 c_backupPool.getPtr(ptr, senderData);
3432 TablePtr tabPtr;
3433 ndbrequire(findTable(ptr, tabPtr, tableId));
3435 FragmentPtr fragPtr;
3436 tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3438 fragPtr.p->node = signal->theData[2];
3440 getFragmentInfo(signal, ptr, tabPtr, fragNo + 1);
3443 void
3444 Backup::getFragmentInfoDone(Signal* signal, BackupRecordPtr ptr)
3446 ptr.p->m_gsn = GSN_DEFINE_BACKUP_CONF;
3447 ptr.p->slaveState.setState(DEFINED);
3448 DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtr();
3449 conf->backupPtr = ptr.i;
3450 conf->backupId = ptr.p->backupId;
3451 sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_CONF, signal,
3452 DefineBackupConf::SignalLength, JBB);
3456 /*****************************************************************************
3458 * Slave functionallity: Start backup
3460 *****************************************************************************/
3461 void
3462 Backup::execSTART_BACKUP_REQ(Signal* signal)
3464 jamEntry();
3466 CRASH_INSERTION((10015));
3468 StartBackupReq* req = (StartBackupReq*)signal->getDataPtr();
3469 const Uint32 ptrI = req->backupPtr;
3471 BackupRecordPtr ptr LINT_SET_PTR;
3472 c_backupPool.getPtr(ptr, ptrI);
3474 ptr.p->slaveState.setState(STARTED);
3475 ptr.p->m_gsn = GSN_START_BACKUP_REQ;
3478 * Start file threads...
3480 BackupFilePtr filePtr;
3481 for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
3483 jam();
3484 if(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD))
3486 jam();
3487 filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
3488 signal->theData[0] = BackupContinueB::START_FILE_THREAD;
3489 signal->theData[1] = filePtr.i;
3490 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
3491 }//if
3492 }//for
3495 * Tell DBTUP to create triggers
3497 TablePtr tabPtr;
3498 ndbrequire(ptr.p->tables.first(tabPtr));
3499 sendCreateTrig(signal, ptr, tabPtr);
3502 /*****************************************************************************
3504 * Slave functionallity: Backup fragment
3506 *****************************************************************************/
3507 void
3508 Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
3510 jamEntry();
3511 BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtr();
3513 CRASH_INSERTION((10016));
3515 const Uint32 ptrI = req->backupPtr;
3516 //const Uint32 backupId = req->backupId;
3517 const Uint32 tableId = req->tableId;
3518 const Uint32 fragNo = req->fragmentNo;
3519 const Uint32 count = req->count;
3522 * Get backup record
3524 BackupRecordPtr ptr LINT_SET_PTR;
3525 c_backupPool.getPtr(ptr, ptrI);
3527 ptr.p->slaveState.setState(SCANNING);
3528 ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REQ;
3531 * Get file
3533 BackupFilePtr filePtr LINT_SET_PTR;
3534 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
3536 ndbrequire(filePtr.p->backupPtr == ptrI);
3537 ndbrequire(filePtr.p->m_flags ==
3538 (BackupFile::BF_OPEN | BackupFile::BF_FILE_THREAD));
3541 * Get table
3543 TablePtr tabPtr;
3544 ndbrequire(findTable(ptr, tabPtr, tableId));
3547 * Get fragment
3549 FragmentPtr fragPtr;
3550 tabPtr.p->fragments.getPtr(fragPtr, fragNo);
3552 ndbrequire(fragPtr.p->scanned == 0);
3553 ndbrequire(fragPtr.p->scanning == 0 ||
3554 refToNode(ptr.p->masterRef) == getOwnNodeId());
3557 * Init operation
3559 if(filePtr.p->tableId != tableId) {
3560 jam();
3561 filePtr.p->operation.init(tabPtr);
3562 filePtr.p->tableId = tableId;
3563 }//if
3566 * Check for space in buffer
3568 if(!filePtr.p->operation.newFragment(tableId, fragPtr.p->fragmentId)) {
3569 jam();
3570 req->count = count + 1;
3571 sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
3572 signal->length());
3573 ptr.p->slaveState.setState(STARTED);
3574 return;
3575 }//if
3578 * Mark things as "in use"
3580 fragPtr.p->scanning = 1;
3581 filePtr.p->fragmentNo = fragPtr.p->fragmentId;
3584 * Start scan
3587 filePtr.p->m_flags |= BackupFile::BF_SCAN_THREAD;
3589 Table & table = * tabPtr.p;
3590 ScanFragReq * req = (ScanFragReq *)signal->getDataPtrSend();
3591 const Uint32 parallelism = 16;
3592 const Uint32 attrLen = 5 + table.noOfAttributes;
3594 req->senderData = filePtr.i;
3595 req->resultRef = reference();
3596 req->schemaVersion = table.schemaVersion;
3597 req->fragmentNoKeyLen = fragPtr.p->fragmentId;
3598 req->requestInfo = 0;
3599 req->savePointId = 0;
3600 req->tableId = table.tableId;
3601 ScanFragReq::setReadCommittedFlag(req->requestInfo, 1);
3602 ScanFragReq::setLockMode(req->requestInfo, 0);
3603 ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
3604 ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
3605 ScanFragReq::setAttrLen(req->requestInfo,attrLen);
3606 ScanFragReq::setTupScanFlag(req->requestInfo, 1);
3607 if (ptr.p->is_lcp())
3609 ScanFragReq::setScanPrio(req->requestInfo, 1);
3610 ScanFragReq::setNoDiskFlag(req->requestInfo, 1);
3611 ScanFragReq::setLcpScanFlag(req->requestInfo, 1);
3613 req->transId1 = 0;
3614 req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
3615 req->clientOpPtr= filePtr.i;
3616 req->batch_size_rows= parallelism;
3617 req->batch_size_bytes= 0;
3618 sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal,
3619 ScanFragReq::SignalLength, JBB);
3621 signal->theData[0] = filePtr.i;
3622 signal->theData[1] = 0;
3623 signal->theData[2] = (BACKUP << 20) + (getOwnNodeId() << 8);
3625 // Return all
3626 signal->theData[3] = table.noOfAttributes;
3627 signal->theData[4] = 0;
3628 signal->theData[5] = 0;
3629 signal->theData[6] = 0;
3630 signal->theData[7] = 0;
3632 Uint32 dataPos = 8;
3633 Ptr<Attribute> attrPtr;
3634 table.attributes.first(attrPtr);
3635 for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
3637 jam();
3640 * LCP should not save disk attributes
3642 ndbrequire(! (ptr.p->is_lcp() &&
3643 attrPtr.p->data.m_flags & Attribute::COL_DISK));
3645 AttributeHeader::init(&signal->theData[dataPos],
3646 attrPtr.p->data.attrId, 0);
3647 dataPos++;
3648 if(dataPos == 25) {
3649 jam();
3650 sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, 25, JBB);
3651 dataPos = 3;
3652 }//if
3653 }//for
3654 if(dataPos != 3) {
3655 jam();
3656 sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, dataPos, JBB);
3657 }//if
3661 void
3662 Backup::execSCAN_HBREP(Signal* signal)
3664 jamEntry();
3667 void
3668 Backup::execTRANSID_AI(Signal* signal)
3670 jamEntry();
3672 const Uint32 filePtrI = signal->theData[0];
3673 //const Uint32 transId1 = signal->theData[1];
3674 //const Uint32 transId2 = signal->theData[2];
3675 const Uint32 dataLen = signal->length() - 3;
3677 BackupFilePtr filePtr LINT_SET_PTR;
3678 c_backupFilePool.getPtr(filePtr, filePtrI);
3680 OperationRecord & op = filePtr.p->operation;
3682 TablePtr tabPtr LINT_SET_PTR;
3683 c_tablePool.getPtr(tabPtr, op.tablePtr);
3685 Table & table = * tabPtr.p;
3688 * Unpack data
3690 op.attrSzTotal += dataLen;
3692 Uint32 srcSz = dataLen;
3693 Uint32 usedSz = 0;
3694 const Uint32 * src = &signal->theData[3];
3696 Ptr<Attribute> attrPtr;
3697 table.attributes.first(attrPtr);
3698 Uint32 columnNo = 0;
3700 while (usedSz < srcSz)
3702 jam();
3705 * Finished with one attribute now find next
3707 const AttributeHeader attrHead(* src);
3708 const Uint32 attrId = attrHead.getAttributeId();
3709 const bool null = attrHead.isNULL();
3710 const Attribute::Data attr = attrPtr.p->data;
3711 ndbrequire(attrId == attr.attrId);
3713 usedSz += attrHead.getHeaderSize();
3714 src += attrHead.getHeaderSize();
3716 if (null) {
3717 jam();
3718 ndbrequire(attr.m_flags & Attribute::COL_NULLABLE);
3719 op.nullVariable();
3720 } else {
3721 Uint32* dst;
3722 Uint32 dstSz = attrHead.getDataSize();
3723 if (attr.m_flags & Attribute::COL_FIXED &&
3724 ! (attr.m_flags & Attribute::COL_NULLABLE)) {
3725 jam();
3726 dst = op.newAttrib(attr.offset, dstSz);
3727 ndbrequire(dstSz == attr.sz32);
3728 } else {
3729 dst = op.newVariable(columnNo, attrHead.getByteSize());
3730 ndbrequire(dstSz <= attr.sz32);
3733 memcpy(dst, src, (dstSz << 2));
3734 src += dstSz;
3735 usedSz += dstSz;
3737 table.attributes.next(attrPtr);
3738 columnNo++;
3741 ndbrequire(usedSz == srcSz);
3742 ndbrequire(op.finished());
3743 op.newRecord(op.dst);
3746 void
3747 Backup::OperationRecord::init(const TablePtr & ptr)
3750 tablePtr = ptr.i;
3751 noOfAttributes = ptr.p->noOfAttributes;
3753 sz_Bitmask = (ptr.p->noOfNull + 31) >> 5;
3754 sz_FixedAttribs = ptr.p->sz_FixedAttributes;
3756 if(ptr.p->noOfVariable == 0) {
3757 jam();
3758 maxRecordSize = 1 + sz_Bitmask + sz_FixedAttribs;
3759 } else {
3760 jam();
3761 maxRecordSize =
3762 1 + sz_Bitmask + 2048 /* Max tuple size */ + 2 * ptr.p->noOfVariable;
3763 }//if
3766 bool
3767 Backup::OperationRecord::newFragment(Uint32 tableId, Uint32 fragNo)
3769 Uint32 * tmp;
3770 const Uint32 headSz = (sizeof(BackupFormat::DataFile::FragmentHeader) >> 2);
3771 const Uint32 sz = headSz + 16 * maxRecordSize;
3773 ndbrequire(sz < dataBuffer.getMaxWrite());
3774 if(dataBuffer.getWritePtr(&tmp, sz)) {
3775 jam();
3776 BackupFormat::DataFile::FragmentHeader * head =
3777 (BackupFormat::DataFile::FragmentHeader*)tmp;
3779 head->SectionType = htonl(BackupFormat::FRAGMENT_HEADER);
3780 head->SectionLength = htonl(headSz);
3781 head->TableId = htonl(tableId);
3782 head->FragmentNo = htonl(fragNo);
3783 head->ChecksumType = htonl(0);
3785 opNoDone = opNoConf = opLen = 0;
3786 newRecord(tmp + headSz);
3787 scanStart = tmp;
3788 scanStop = (tmp + headSz);
3790 noOfRecords = 0;
3791 noOfBytes = 0;
3792 return true;
3793 }//if
3794 return false;
3797 bool
3798 Backup::OperationRecord::fragComplete(Uint32 tableId, Uint32 fragNo, bool fill_record)
3800 Uint32 * tmp;
3801 const Uint32 footSz = sizeof(BackupFormat::DataFile::FragmentFooter) >> 2;
3802 Uint32 sz = footSz + 1;
3804 if (fill_record)
3806 Uint32 * new_tmp;
3807 if (!dataBuffer.getWritePtr(&tmp, sz))
3808 return false;
3809 new_tmp = tmp + sz;
3811 if ((UintPtr)new_tmp & (sizeof(Page32)-1))
3813 /* padding is needed to get full write */
3814 new_tmp += 2 /* to fit empty header minimum 2 words*/;
3815 new_tmp = (Uint32 *)(((UintPtr)new_tmp + sizeof(Page32)-1) &
3816 ~(UintPtr)(sizeof(Page32)-1));
3817 /* new write sz */
3818 sz = new_tmp - tmp;
3822 if(dataBuffer.getWritePtr(&tmp, sz)) {
3823 jam();
3824 * tmp = 0; // Finish record stream
3825 tmp++;
3826 BackupFormat::DataFile::FragmentFooter * foot =
3827 (BackupFormat::DataFile::FragmentFooter*)tmp;
3828 foot->SectionType = htonl(BackupFormat::FRAGMENT_FOOTER);
3829 foot->SectionLength = htonl(footSz);
3830 foot->TableId = htonl(tableId);
3831 foot->FragmentNo = htonl(fragNo);
3832 foot->NoOfRecords = htonl(noOfRecords);
3833 foot->Checksum = htonl(0);
3835 if (sz != footSz + 1)
3837 tmp += footSz;
3838 memset(tmp, 0, (sz - footSz - 1) * 4);
3839 *tmp = htonl(BackupFormat::EMPTY_ENTRY);
3840 tmp++;
3841 *tmp = htonl(sz - footSz - 1);
3844 dataBuffer.updateWritePtr(sz);
3845 return true;
3846 }//if
3847 return false;
3850 bool
3851 Backup::OperationRecord::newScan()
3853 Uint32 * tmp;
3854 ndbrequire(16 * maxRecordSize < dataBuffer.getMaxWrite());
3855 if(dataBuffer.getWritePtr(&tmp, 16 * maxRecordSize)) {
3856 jam();
3857 opNoDone = opNoConf = opLen = 0;
3858 newRecord(tmp);
3859 scanStart = tmp;
3860 scanStop = tmp;
3861 return true;
3862 }//if
3863 return false;
3866 bool
3867 Backup::OperationRecord::closeScan()
3869 opNoDone = opNoConf = opLen = 0;
3870 return true;
3873 bool
3874 Backup::OperationRecord::scanConf(Uint32 noOfOps, Uint32 total_len)
3876 const Uint32 done = opNoDone-opNoConf;
3878 ndbrequire(noOfOps == done);
3879 ndbrequire(opLen == total_len);
3880 opNoConf = opNoDone;
3882 const Uint32 len = (scanStop - scanStart);
3883 ndbrequire(len < dataBuffer.getMaxWrite());
3884 dataBuffer.updateWritePtr(len);
3885 noOfBytes += (len << 2);
3886 return true;
3889 void
3890 Backup::execSCAN_FRAGREF(Signal* signal)
3892 jamEntry();
3894 ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr();
3896 const Uint32 filePtrI = ref->senderData;
3897 BackupFilePtr filePtr LINT_SET_PTR;
3898 c_backupFilePool.getPtr(filePtr, filePtrI);
3900 filePtr.p->errorCode = ref->errorCode;
3901 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3903 backupFragmentRef(signal, filePtr);
3906 void
3907 Backup::execSCAN_FRAGCONF(Signal* signal)
3909 jamEntry();
3911 CRASH_INSERTION((10017));
3913 ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr();
3915 const Uint32 filePtrI = conf->senderData;
3916 BackupFilePtr filePtr LINT_SET_PTR;
3917 c_backupFilePool.getPtr(filePtr, filePtrI);
3919 OperationRecord & op = filePtr.p->operation;
3921 op.scanConf(conf->completedOps, conf->total_len);
3922 const Uint32 completed = conf->fragmentCompleted;
3923 if(completed != 2) {
3924 jam();
3926 checkScan(signal, filePtr);
3927 return;
3928 }//if
3930 fragmentCompleted(signal, filePtr);
3933 void
3934 Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
3936 jam();
3938 if(filePtr.p->errorCode != 0)
3940 jam();
3941 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3942 backupFragmentRef(signal, filePtr); // Scan completed
3943 return;
3944 }//if
3946 BackupRecordPtr ptr LINT_SET_PTR;
3947 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
3949 OperationRecord & op = filePtr.p->operation;
3950 if(!op.fragComplete(filePtr.p->tableId, filePtr.p->fragmentNo,
3951 c_defaults.m_o_direct))
3953 jam();
3954 signal->theData[0] = BackupContinueB::BUFFER_FULL_FRAG_COMPLETE;
3955 signal->theData[1] = filePtr.i;
3956 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
3957 return;
3958 }//if
3960 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
3962 if (ptr.p->is_lcp())
3964 ptr.p->slaveState.setState(STOPPING);
3965 filePtr.p->operation.dataBuffer.eof();
3967 else
3969 BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
3970 conf->backupId = ptr.p->backupId;
3971 conf->backupPtr = ptr.i;
3972 conf->tableId = filePtr.p->tableId;
3973 conf->fragmentNo = filePtr.p->fragmentNo;
3974 conf->noOfRecordsLow = (Uint32)(op.noOfRecords & 0xFFFFFFFF);
3975 conf->noOfRecordsHigh = (Uint32)(op.noOfRecords >> 32);
3976 conf->noOfBytesLow = (Uint32)(op.noOfBytes & 0xFFFFFFFF);
3977 conf->noOfBytesHigh = (Uint32)(op.noOfBytes >> 32);
3978 sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
3979 BackupFragmentConf::SignalLength, JBB);
3981 ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_CONF;
3982 ptr.p->slaveState.setState(STARTED);
3984 return;
3987 void
3988 Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr)
3990 BackupRecordPtr ptr LINT_SET_PTR;
3991 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
3993 ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF;
3995 BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtrSend();
3996 ref->backupId = ptr.p->backupId;
3997 ref->backupPtr = ptr.i;
3998 ref->nodeId = getOwnNodeId();
3999 ref->errorCode = filePtr.p->errorCode;
4000 sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal,
4001 BackupFragmentRef::SignalLength, JBB);
4004 void
4005 Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
4007 OperationRecord & op = filePtr.p->operation;
4009 if(filePtr.p->errorCode != 0)
4011 jam();
4014 * Close scan
4016 op.closeScan();
4017 ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
4018 req->senderData = filePtr.i;
4019 req->closeFlag = 1;
4020 req->transId1 = 0;
4021 req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
4022 sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4023 ScanFragNextReq::SignalLength, JBB);
4024 return;
4025 }//if
4027 if(op.newScan()) {
4028 jam();
4030 ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
4031 req->senderData = filePtr.i;
4032 req->closeFlag = 0;
4033 req->transId1 = 0;
4034 req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
4035 req->batch_size_rows= 16;
4036 req->batch_size_bytes= 0;
4038 if (ERROR_INSERTED(10036) &&
4039 filePtr.p->tableId >= 2 &&
4040 filePtr.p->operation.noOfRecords > 0)
4042 ndbout_c("halting backup for table %d fragment: %d after %llu records",
4043 filePtr.p->tableId,
4044 filePtr.p->fragmentNo,
4045 filePtr.p->operation.noOfRecords);
4046 memmove(signal->theData+1, signal->theData,
4047 4*ScanFragNextReq::SignalLength);
4048 signal->theData[0] = BackupContinueB::ZDELAY_SCAN_NEXT;
4049 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
4050 300, 1+ScanFragNextReq::SignalLength);
4051 return;
4053 if(ERROR_INSERTED(10032))
4054 sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4055 100, ScanFragNextReq::SignalLength);
4056 else if(ERROR_INSERTED(10033))
4058 SET_ERROR_INSERT_VALUE(10032);
4059 sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4060 10000, ScanFragNextReq::SignalLength);
4062 BackupRecordPtr ptr LINT_SET_PTR;
4063 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4064 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4065 ord->backupId = ptr.p->backupId;
4066 ord->backupPtr = ptr.i;
4067 ord->requestType = AbortBackupOrd::FileOrScanError;
4068 ord->senderData= ptr.i;
4069 sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
4070 AbortBackupOrd::SignalLength, JBB);
4072 else
4073 sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
4074 ScanFragNextReq::SignalLength, JBB);
4075 return;
4076 }//if
4078 signal->theData[0] = BackupContinueB::BUFFER_FULL_SCAN;
4079 signal->theData[1] = filePtr.i;
4080 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
4083 void
4084 Backup::execFSAPPENDREF(Signal* signal)
4086 jamEntry();
4088 FsRef * ref = (FsRef *)signal->getDataPtr();
4090 const Uint32 filePtrI = ref->userPointer;
4091 const Uint32 errCode = ref->errorCode;
4093 BackupFilePtr filePtr LINT_SET_PTR;
4094 c_backupFilePool.getPtr(filePtr, filePtrI);
4096 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4097 filePtr.p->errorCode = errCode;
4099 checkFile(signal, filePtr);
4102 void
4103 Backup::execFSAPPENDCONF(Signal* signal)
4105 jamEntry();
4107 CRASH_INSERTION((10018));
4109 //FsConf * conf = (FsConf*)signal->getDataPtr();
4110 const Uint32 filePtrI = signal->theData[0]; //conf->userPointer;
4111 const Uint32 bytes = signal->theData[1]; //conf->bytes;
4113 BackupFilePtr filePtr LINT_SET_PTR;
4114 c_backupFilePool.getPtr(filePtr, filePtrI);
4116 OperationRecord & op = filePtr.p->operation;
4118 op.dataBuffer.updateReadPtr(bytes >> 2);
4120 checkFile(signal, filePtr);
4124 This routine handles two problems with writing to disk during local
4125 checkpoints and backups. The first problem is that we need to limit
4126 the writing to ensure that we don't use too much CPU and disk resources
4127 for backups and checkpoints. The perfect solution to this is to use
4128 a dynamic algorithm that adapts to the environment. Until we have
4129 implemented this we can satisfy ourselves with an algorithm that
4130 uses a configurable limit.
4132 The second problem is that in Linux we can get severe problems if we
4133 write very much to the disk without synching. In the worst case we
4134 can have Gigabytes of data in the Linux page cache before we reach
4135 the limit of how much we can write. If this happens the performance
4136 will drop significantly when we reach this limit since the Linux flush
4137 daemon will spend a few minutes on writing out the page cache to disk.
4138 To avoid this we ensure that a file never have more than a certain
4139 amount of data outstanding before synch. This variable is also
4140 configurable.
4142 bool
4143 Backup::ready_to_write(bool ready, Uint32 sz, bool eof, BackupFile *fileP)
4145 #if 0
4146 ndbout << "ready_to_write: ready = " << ready << " eof = " << eof;
4147 ndbout << " sz = " << sz << endl;
4148 ndbout << "words this period = " << m_words_written_this_period;
4149 ndbout << endl << "overflow disk write = " << m_overflow_disk_write;
4150 ndbout << endl << "Current Millisecond is = ";
4151 ndbout << NdbTick_CurrentMillisecond() << endl;
4152 #endif
4153 if ((ready || eof) &&
4154 m_words_written_this_period <= m_curr_disk_write_speed)
4157 We have a buffer ready to write or we have reached end of
4158 file and thus we must write the last before closing the
4159 file.
4160 We have already check that we are allowed to write at this
4161 moment. We only worry about history of last 100 milliseconds.
4162 What happened before that is of no interest since a disk
4163 write that was issued more than 100 milliseconds should be
4164 completed by now.
4166 int overflow;
4167 m_words_written_this_period += sz;
4168 overflow = m_words_written_this_period - m_curr_disk_write_speed;
4169 if (overflow > 0)
4170 m_overflow_disk_write = overflow;
4171 #if 0
4172 ndbout << "Will write with " << endl;
4173 ndbout << endl;
4174 #endif
4175 return true;
4177 else
4179 #if 0
4180 ndbout << "Will not write now" << endl << endl;
4181 #endif
4182 return false;
4186 void
4187 Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
4190 #ifdef DEBUG_ABORT
4191 // ndbout_c("---- check file filePtr.i = %u", filePtr.i);
4192 #endif
4194 OperationRecord & op = filePtr.p->operation;
4195 Uint32 *tmp = NULL;
4196 Uint32 sz = 0;
4197 bool eof = FALSE;
4198 bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
4199 #if 0
4200 ndbout << "Ptr to data = " << hex << tmp << endl;
4201 #endif
4202 BackupRecordPtr ptr LINT_SET_PTR;
4203 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4205 if (ERROR_INSERTED(10036))
4207 jam();
4208 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4209 filePtr.p->errorCode = 2810;
4210 ptr.p->setErrorCode(2810);
4212 if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
4214 jam();
4215 closeFile(signal, ptr, filePtr);
4217 return;
4220 if(filePtr.p->errorCode != 0)
4222 jam();
4223 ptr.p->setErrorCode(filePtr.p->errorCode);
4225 if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
4227 jam();
4228 closeFile(signal, ptr, filePtr);
4230 return;
4233 if (!ready_to_write(ready, sz, eof, filePtr.p))
4235 jam();
4236 signal->theData[0] = BackupContinueB::BUFFER_UNDERFLOW;
4237 signal->theData[1] = filePtr.i;
4238 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 20, 2);
4239 return;
4241 else if (sz > 0)
4243 jam();
4244 FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend();
4245 req->filePointer = filePtr.p->filePointer;
4246 req->userPointer = filePtr.i;
4247 req->userReference = reference();
4248 req->varIndex = 0;
4249 req->offset = tmp - c_startOfPages;
4250 req->size = sz;
4251 req->synch_flag = 0;
4253 sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal,
4254 FsAppendReq::SignalLength, JBA);
4255 return;
4258 Uint32 flags = filePtr.p->m_flags;
4259 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
4261 ndbrequire(flags & BackupFile::BF_OPEN);
4262 ndbrequire(flags & BackupFile::BF_FILE_THREAD);
4264 closeFile(signal, ptr, filePtr);
4268 /****************************************************************************
4270 * Slave functionallity: Perform logging
4272 ****************************************************************************/
4273 void
4274 Backup::execBACKUP_TRIG_REQ(Signal* signal)
4277 TUP asks if this trigger is to be fired on this node.
4279 TriggerPtr trigPtr LINT_SET_PTR;
4280 TablePtr tabPtr LINT_SET_PTR;
4281 FragmentPtr fragPtr;
4282 Uint32 trigger_id = signal->theData[0];
4283 Uint32 frag_id = signal->theData[1];
4284 Uint32 result;
4286 jamEntry();
4288 c_triggerPool.getPtr(trigPtr, trigger_id);
4290 c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
4291 tabPtr.p->fragments.getPtr(fragPtr, frag_id);
4292 if (fragPtr.p->node != getOwnNodeId()) {
4294 jam();
4295 result = ZFALSE;
4296 } else {
4297 jam();
4298 result = ZTRUE;
4299 }//if
4300 signal->theData[0] = result;
4303 void
4304 Backup::execTRIG_ATTRINFO(Signal* signal) {
4305 jamEntry();
4307 CRASH_INSERTION((10019));
4309 TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr();
4311 TriggerPtr trigPtr LINT_SET_PTR;
4312 c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
4313 ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
4315 if(trigPtr.p->errorCode != 0) {
4316 jam();
4317 return;
4318 }//if
4320 if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
4321 jam();
4323 * Backup is doing REDO logging and don't need before values
4325 return;
4326 }//if
4328 BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
4329 if(logEntry == 0)
4331 jam();
4332 Uint32 * dst;
4333 FsBuffer & buf = trigPtr.p->operation->dataBuffer;
4334 ndbrequire(trigPtr.p->maxRecordSize <= buf.getMaxWrite());
4336 if(ERROR_INSERTED(10030) ||
4337 !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize))
4339 jam();
4340 Uint32 save[TrigAttrInfo::StaticLength];
4341 memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength);
4342 BackupRecordPtr ptr LINT_SET_PTR;
4343 c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
4344 trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull;
4345 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4346 ord->backupId = ptr.p->backupId;
4347 ord->backupPtr = ptr.i;
4348 ord->requestType = AbortBackupOrd::LogBufferFull;
4349 ord->senderData= ptr.i;
4350 sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
4351 AbortBackupOrd::SignalLength, JBB);
4353 memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength);
4354 return;
4355 }//if
4357 logEntry = (BackupFormat::LogFile::LogEntry *)dst;
4358 trigPtr.p->logEntry = logEntry;
4359 logEntry->Length = 0;
4360 logEntry->TableId = htonl(trigPtr.p->tableId);
4363 if(trigPtr.p->event==0)
4364 logEntry->TriggerEvent= htonl(TriggerEvent::TE_INSERT);
4365 else if(trigPtr.p->event==1)
4366 logEntry->TriggerEvent= htonl(TriggerEvent::TE_UPDATE);
4367 else if(trigPtr.p->event==2)
4368 logEntry->TriggerEvent= htonl(TriggerEvent::TE_DELETE);
4369 else {
4370 ndbout << "Bad Event: " << trigPtr.p->event << endl;
4371 ndbrequire(false);
4373 } else {
4374 ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId));
4375 // ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event));
4376 }//if
4378 const Uint32 pos = logEntry->Length;
4379 const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
4380 memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2);
4382 logEntry->Length = pos + dataLen;
4385 void
4386 Backup::execFIRE_TRIG_ORD(Signal* signal)
4388 jamEntry();
4389 FireTrigOrd* trg = (FireTrigOrd*)signal->getDataPtr();
4391 const Uint32 gci = trg->getGCI();
4392 const Uint32 trI = trg->getTriggerId();
4393 const Uint32 fragId = trg->fragId;
4395 TriggerPtr trigPtr LINT_SET_PTR;
4396 c_triggerPool.getPtr(trigPtr, trI);
4398 ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
4400 if(trigPtr.p->errorCode != 0) {
4401 jam();
4402 return;
4403 }//if
4405 ndbrequire(trigPtr.p->logEntry != 0);
4406 Uint32 len = trigPtr.p->logEntry->Length;
4407 trigPtr.p->logEntry->FragId = htonl(fragId);
4409 BackupRecordPtr ptr LINT_SET_PTR;
4410 c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
4411 if(gci != ptr.p->currGCP)
4413 jam();
4414 trigPtr.p->logEntry->TriggerEvent|= htonl(0x10000);
4415 trigPtr.p->logEntry->Data[len] = htonl(gci);
4416 len++;
4417 ptr.p->currGCP = gci;
4420 len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
4421 trigPtr.p->logEntry->Length = htonl(len);
4423 ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
4424 trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
4425 trigPtr.p->logEntry = 0;
4427 trigPtr.p->operation->noOfBytes += (len + 1) << 2;
4428 trigPtr.p->operation->noOfRecords += 1;
4431 void
4432 Backup::sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr,
4433 Uint32 requestType)
4435 jam();
4436 AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
4437 ord->backupId = ptr.p->backupId;
4438 ord->backupPtr = ptr.i;
4439 ord->requestType = requestType;
4440 ord->senderData= ptr.i;
4441 NodePtr node;
4442 for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
4443 jam();
4444 const Uint32 nodeId = node.p->nodeId;
4445 if(node.p->alive && ptr.p->nodes.get(nodeId)) {
4446 jam();
4447 sendSignal(numberToRef(BACKUP, nodeId), GSN_ABORT_BACKUP_ORD, signal,
4448 AbortBackupOrd::SignalLength, JBB);
4449 }//if
4450 }//for
4453 /*****************************************************************************
4455 * Slave functionallity: Stop backup
4457 *****************************************************************************/
4458 void
4459 Backup::execSTOP_BACKUP_REQ(Signal* signal)
4461 jamEntry();
4462 StopBackupReq * req = (StopBackupReq*)signal->getDataPtr();
4464 CRASH_INSERTION((10020));
4466 const Uint32 ptrI = req->backupPtr;
4467 //const Uint32 backupId = req->backupId;
4468 const Uint32 startGCP = req->startGCP;
4469 const Uint32 stopGCP = req->stopGCP;
4472 * At least one GCP must have passed
4474 ndbrequire(stopGCP > startGCP);
4477 * Get backup record
4479 BackupRecordPtr ptr LINT_SET_PTR;
4480 c_backupPool.getPtr(ptr, ptrI);
4482 ptr.p->slaveState.setState(STOPPING);
4483 ptr.p->m_gsn = GSN_STOP_BACKUP_REQ;
4484 ptr.p->startGCP= startGCP;
4485 ptr.p->stopGCP= stopGCP;
4488 * Destroy the triggers in local DBTUP we created
4490 sendDropTrig(signal, ptr);
4493 void
4494 Backup::closeFiles(Signal* sig, BackupRecordPtr ptr)
4497 * Close all files
4499 BackupFilePtr filePtr;
4500 int openCount = 0;
4501 for(ptr.p->files.first(filePtr); filePtr.i!=RNIL; ptr.p->files.next(filePtr))
4503 if(! (filePtr.p->m_flags & BackupFile::BF_OPEN))
4505 jam();
4506 continue;
4509 jam();
4510 openCount++;
4512 if(filePtr.p->m_flags & BackupFile::BF_CLOSING)
4514 jam();
4515 continue;
4516 }//if
4518 filePtr.p->operation.dataBuffer.eof();
4519 if(filePtr.p->m_flags & BackupFile::BF_FILE_THREAD)
4521 jam();
4522 #ifdef DEBUG_ABORT
4523 ndbout_c("Close files fileRunning == 1, filePtr.i=%u", filePtr.i);
4524 #endif
4526 else
4528 jam();
4529 closeFile(sig, ptr, filePtr);
4533 if(openCount == 0){
4534 jam();
4535 closeFilesDone(sig, ptr);
4536 }//if
4539 void
4540 Backup::closeFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr)
4542 ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPEN);
4543 ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPENING));
4544 ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_CLOSING));
4545 filePtr.p->m_flags |= BackupFile::BF_CLOSING;
4547 FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend();
4548 req->filePointer = filePtr.p->filePointer;
4549 req->userPointer = filePtr.i;
4550 req->userReference = reference();
4551 req->fileFlag = 0;
4553 if (ptr.p->errorCode)
4555 FsCloseReq::setRemoveFileFlag(req->fileFlag, 1);
4558 #ifdef DEBUG_ABORT
4559 ndbout_c("***** a FSCLOSEREQ filePtr.i = %u flags: %x",
4560 filePtr.i, filePtr.p->m_flags);
4561 #endif
4562 sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
4566 void
4567 Backup::execFSCLOSEREF(Signal* signal)
4569 jamEntry();
4571 FsRef * ref = (FsRef*)signal->getDataPtr();
4572 const Uint32 filePtrI = ref->userPointer;
4574 BackupFilePtr filePtr LINT_SET_PTR;
4575 c_backupFilePool.getPtr(filePtr, filePtrI);
4577 BackupRecordPtr ptr LINT_SET_PTR;
4578 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4580 FsConf * conf = (FsConf*)signal->getDataPtr();
4581 conf->userPointer = filePtrI;
4583 execFSCLOSECONF(signal);
4586 void
4587 Backup::execFSCLOSECONF(Signal* signal)
4589 jamEntry();
4591 FsConf * conf = (FsConf*)signal->getDataPtr();
4592 const Uint32 filePtrI = conf->userPointer;
4594 BackupFilePtr filePtr LINT_SET_PTR;
4595 c_backupFilePool.getPtr(filePtr, filePtrI);
4597 #ifdef DEBUG_ABORT
4598 ndbout_c("***** FSCLOSECONF filePtrI = %u", filePtrI);
4599 #endif
4601 ndbrequire(filePtr.p->m_flags == (BackupFile::BF_OPEN |
4602 BackupFile::BF_CLOSING));
4605 filePtr.p->m_flags &= ~(Uint32)(BackupFile::BF_OPEN |BackupFile::BF_CLOSING);
4606 filePtr.p->operation.dataBuffer.reset();
4608 BackupRecordPtr ptr LINT_SET_PTR;
4609 c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
4610 closeFiles(signal, ptr);
4613 void
4614 Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr)
4616 jam();
4618 if(ptr.p->is_lcp())
4620 lcp_close_file_conf(signal, ptr);
4621 return;
4624 jam();
4626 //error when do insert footer or close file
4627 if(ptr.p->checkError())
4629 StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
4630 ref->backupPtr = ptr.i;
4631 ref->backupId = ptr.p->backupId;
4632 ref->errorCode = ptr.p->errorCode;
4633 ref->nodeId = getOwnNodeId();
4634 sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_REF, signal,
4635 StopBackupConf::SignalLength, JBB);
4637 ptr.p->m_gsn = GSN_STOP_BACKUP_REF;
4638 ptr.p->slaveState.setState(CLEANING);
4639 return;
4642 StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend();
4643 conf->backupId = ptr.p->backupId;
4644 conf->backupPtr = ptr.i;
4646 BackupFilePtr filePtr LINT_SET_PTR;
4647 if(ptr.p->logFilePtr != RNIL)
4649 ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
4650 conf->noOfLogBytes= filePtr.p->operation.noOfBytes;
4651 conf->noOfLogRecords= filePtr.p->operation.noOfRecords;
4653 else
4655 conf->noOfLogBytes= 0;
4656 conf->noOfLogRecords= 0;
4659 sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal,
4660 StopBackupConf::SignalLength, JBB);
4662 ptr.p->m_gsn = GSN_STOP_BACKUP_CONF;
4663 ptr.p->slaveState.setState(CLEANING);
4666 /*****************************************************************************
4668 * Slave functionallity: Abort backup
4670 *****************************************************************************/
4671 /*****************************************************************************
4673 * Slave functionallity: Abort backup
4675 *****************************************************************************/
4676 void
4677 Backup::execABORT_BACKUP_ORD(Signal* signal)
4679 jamEntry();
4680 AbortBackupOrd* ord = (AbortBackupOrd*)signal->getDataPtr();
4682 const Uint32 backupId = ord->backupId;
4683 const AbortBackupOrd::RequestType requestType =
4684 (AbortBackupOrd::RequestType)ord->requestType;
4685 const Uint32 senderData = ord->senderData;
4687 #ifdef DEBUG_ABORT
4688 ndbout_c("******** ABORT_BACKUP_ORD ********* nodeId = %u",
4689 refToNode(signal->getSendersBlockRef()));
4690 ndbout_c("backupId = %u, requestType = %u, senderData = %u, ",
4691 backupId, requestType, senderData);
4692 dumpUsedResources();
4693 #endif
4695 BackupRecordPtr ptr LINT_SET_PTR;
4696 if(requestType == AbortBackupOrd::ClientAbort) {
4697 if (getOwnNodeId() != getMasterNodeId()) {
4698 jam();
4699 // forward to master
4700 #ifdef DEBUG_ABORT
4701 ndbout_c("---- Forward to master nodeId = %u", getMasterNodeId());
4702 #endif
4703 sendSignal(calcBackupBlockRef(getMasterNodeId()), GSN_ABORT_BACKUP_ORD,
4704 signal, AbortBackupOrd::SignalLength, JBB);
4705 return;
4707 jam();
4708 for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
4709 jam();
4710 if(ptr.p->backupId == backupId && ptr.p->clientData == senderData) {
4711 jam();
4712 break;
4713 }//if
4714 }//for
4715 if(ptr.i == RNIL) {
4716 jam();
4717 return;
4718 }//if
4719 } else {
4720 if (c_backupPool.findId(senderData)) {
4721 jam();
4722 c_backupPool.getPtr(ptr, senderData);
4723 } else {
4724 jam();
4725 #ifdef DEBUG_ABORT
4726 ndbout_c("Backup: abort request type=%u on id=%u,%u not found",
4727 requestType, backupId, senderData);
4728 #endif
4729 return;
4731 }//if
4733 ptr.p->m_gsn = GSN_ABORT_BACKUP_ORD;
4734 const bool isCoordinator = (ptr.p->masterRef == reference());
4736 bool ok = false;
4737 switch(requestType){
4740 * Requests sent to master
4742 case AbortBackupOrd::ClientAbort:
4743 jam();
4744 // fall through
4745 case AbortBackupOrd::LogBufferFull:
4746 jam();
4747 // fall through
4748 case AbortBackupOrd::FileOrScanError:
4749 jam();
4750 ndbrequire(isCoordinator);
4751 ptr.p->setErrorCode(requestType);
4752 if(ptr.p->masterData.gsn == GSN_BACKUP_FRAGMENT_REQ)
4755 * Only scans are actively aborted
4757 abort_scan(signal, ptr);
4759 return;
4762 * Requests sent to slave
4764 case AbortBackupOrd::AbortScan:
4765 jam();
4766 ptr.p->setErrorCode(requestType);
4767 return;
4769 case AbortBackupOrd::BackupComplete:
4770 jam();
4771 cleanup(signal, ptr);
4772 return;
4773 case AbortBackupOrd::BackupFailure:
4774 case AbortBackupOrd::BackupFailureDueToNodeFail:
4775 case AbortBackupOrd::OkToClean:
4776 case AbortBackupOrd::IncompatibleVersions:
4777 #ifndef VM_TRACE
4778 default:
4779 #endif
4780 ptr.p->setErrorCode(requestType);
4781 ok= true;
4783 ndbrequire(ok);
4785 ptr.p->masterRef = reference();
4786 ptr.p->nodes.clear();
4787 ptr.p->nodes.set(getOwnNodeId());
4790 ptr.p->stopGCP= ptr.p->startGCP + 1;
4791 sendStopBackup(signal, ptr);
4795 void
4796 Backup::dumpUsedResources()
4798 jam();
4799 BackupRecordPtr ptr;
4801 for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
4802 ndbout_c("Backup id=%u, slaveState.getState = %u, errorCode=%u",
4803 ptr.p->backupId,
4804 ptr.p->slaveState.getState(),
4805 ptr.p->errorCode);
4807 TablePtr tabPtr;
4808 for(ptr.p->tables.first(tabPtr);
4809 tabPtr.i != RNIL;
4810 ptr.p->tables.next(tabPtr)) {
4811 jam();
4812 for(Uint32 j = 0; j<3; j++) {
4813 jam();
4814 TriggerPtr trigPtr LINT_SET_PTR;
4815 if(tabPtr.p->triggerAllocated[j]) {
4816 jam();
4817 c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
4818 ndbout_c("Allocated[%u] Triggerid = %u, event = %u",
4820 tabPtr.p->triggerIds[j],
4821 trigPtr.p->event);
4822 }//if
4823 }//for
4824 }//for
4826 BackupFilePtr filePtr;
4827 for(ptr.p->files.first(filePtr);
4828 filePtr.i != RNIL;
4829 ptr.p->files.next(filePtr)) {
4830 jam();
4831 ndbout_c("filePtr.i = %u, flags: H'%x ",
4832 filePtr.i, filePtr.p->m_flags);
4833 }//for
4837 void
4838 Backup::cleanup(Signal* signal, BackupRecordPtr ptr)
4841 TablePtr tabPtr;
4842 for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;ptr.p->tables.next(tabPtr))
4844 jam();
4845 tabPtr.p->attributes.release();
4846 tabPtr.p->fragments.release();
4847 for(Uint32 j = 0; j<3; j++) {
4848 jam();
4849 TriggerPtr trigPtr LINT_SET_PTR;
4850 if(tabPtr.p->triggerAllocated[j]) {
4851 jam();
4852 c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
4853 trigPtr.p->event = ILLEGAL_TRIGGER_ID;
4854 tabPtr.p->triggerAllocated[j] = false;
4855 }//if
4856 tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID;
4857 }//for
4859 signal->theData[0] = tabPtr.p->tableId;
4860 signal->theData[1] = 0; // unlock
4861 EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
4863 }//for
4865 BackupFilePtr filePtr;
4866 for(ptr.p->files.first(filePtr);filePtr.i != RNIL;ptr.p->files.next(filePtr))
4868 jam();
4869 ndbrequire(filePtr.p->m_flags == 0);
4870 filePtr.p->pages.release();
4871 }//for
4873 ptr.p->files.release();
4874 ptr.p->tables.release();
4875 ptr.p->triggers.release();
4876 ptr.p->backupId = ~0;
4878 if(ptr.p->checkError())
4879 removeBackup(signal, ptr);
4880 else
4881 c_backups.release(ptr);
4885 void
4886 Backup::removeBackup(Signal* signal, BackupRecordPtr ptr)
4888 jam();
4890 FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
4891 req->userReference = reference();
4892 req->userPointer = ptr.i;
4893 req->directory = 1;
4894 req->ownDirectory = 1;
4895 FsOpenReq::setVersion(req->fileNumber, 2);
4896 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
4897 FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
4898 FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
4899 sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
4900 FsRemoveReq::SignalLength, JBA);
4903 void
4904 Backup::execFSREMOVEREF(Signal* signal)
4906 jamEntry();
4907 FsRef * ref = (FsRef*)signal->getDataPtr();
4908 const Uint32 ptrI = ref->userPointer;
4910 FsConf * conf = (FsConf*)signal->getDataPtr();
4911 conf->userPointer = ptrI;
4912 execFSREMOVECONF(signal);
4915 void
4916 Backup::execFSREMOVECONF(Signal* signal){
4917 jamEntry();
4919 FsConf * conf = (FsConf*)signal->getDataPtr();
4920 const Uint32 ptrI = conf->userPointer;
4923 * Get backup record
4925 BackupRecordPtr ptr LINT_SET_PTR;
4926 c_backupPool.getPtr(ptr, ptrI);
4927 c_backups.release(ptr);
4931 * LCP
4933 void
4934 Backup::execLCP_PREPARE_REQ(Signal* signal)
4936 jamEntry();
4937 LcpPrepareReq req = *(LcpPrepareReq*)signal->getDataPtr();
4939 BackupRecordPtr ptr LINT_SET_PTR;
4940 c_backupPool.getPtr(ptr, req.backupPtr);
4942 ptr.p->m_gsn = GSN_LCP_PREPARE_REQ;
4944 TablePtr tabPtr;
4945 FragmentPtr fragPtr;
4946 if (!ptr.p->tables.isEmpty())
4948 jam();
4949 ndbrequire(ptr.p->errorCode);
4950 ptr.p->tables.first(tabPtr);
4951 if (tabPtr.p->tableId == req.tableId)
4953 jam();
4954 ndbrequire(!tabPtr.p->fragments.empty());
4955 tabPtr.p->fragments.getPtr(fragPtr, 0);
4956 fragPtr.p->fragmentId = req.fragmentId;
4957 defineBackupRef(signal, ptr, ptr.p->errorCode);
4958 return;
4960 else
4962 jam();
4963 tabPtr.p->attributes.release();
4964 tabPtr.p->fragments.release();
4965 ptr.p->tables.release();
4966 ptr.p->errorCode = 0;
4967 // fall-through
4971 if(!ptr.p->tables.seize(tabPtr) || !tabPtr.p->fragments.seize(1))
4973 if(!tabPtr.isNull())
4974 ptr.p->tables.release();
4975 ndbrequire(false); // TODO
4977 tabPtr.p->tableId = req.tableId;
4978 tabPtr.p->fragments.getPtr(fragPtr, 0);
4979 tabPtr.p->tableType = DictTabInfo::UserTable;
4980 fragPtr.p->fragmentId = req.fragmentId;
4981 fragPtr.p->lcp_no = req.lcpNo;
4982 fragPtr.p->scanned = 0;
4983 fragPtr.p->scanning = 0;
4984 fragPtr.p->tableId = req.tableId;
4986 ptr.p->backupId= req.backupId;
4987 lcp_open_file(signal, ptr);
4990 void
4991 Backup::lcp_close_file_conf(Signal* signal, BackupRecordPtr ptr)
4993 jam();
4995 TablePtr tabPtr;
4996 ndbrequire(ptr.p->tables.first(tabPtr));
4997 Uint32 tableId = tabPtr.p->tableId;
4999 BackupFilePtr filePtr LINT_SET_PTR;
5000 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5001 ndbrequire(filePtr.p->m_flags == 0);
5003 if (ptr.p->m_gsn == GSN_LCP_PREPARE_REQ)
5005 jam();
5006 defineBackupRef(signal, ptr, ptr.p->errorCode);
5007 return;
5010 FragmentPtr fragPtr;
5011 tabPtr.p->fragments.getPtr(fragPtr, 0);
5012 Uint32 fragmentId = fragPtr.p->fragmentId;
5014 tabPtr.p->attributes.release();
5015 tabPtr.p->fragments.release();
5016 ptr.p->tables.release();
5017 ptr.p->errorCode = 0;
5019 BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
5020 conf->backupId = ptr.p->backupId;
5021 conf->backupPtr = ptr.i;
5022 conf->tableId = tableId;
5023 conf->fragmentNo = fragmentId;
5024 conf->noOfRecordsLow = 0;
5025 conf->noOfRecordsHigh = 0;
5026 conf->noOfBytesLow = 0;
5027 conf->noOfBytesHigh = 0;
5028 sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
5029 BackupFragmentConf::SignalLength, JBB);
5032 void
5033 Backup::lcp_open_file(Signal* signal, BackupRecordPtr ptr)
5035 FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
5036 req->userReference = reference();
5037 req->fileFlags =
5038 FsOpenReq::OM_WRITEONLY |
5039 FsOpenReq::OM_TRUNCATE |
5040 FsOpenReq::OM_CREATE |
5041 FsOpenReq::OM_APPEND |
5042 FsOpenReq::OM_AUTOSYNC;
5043 if (c_defaults.m_o_direct)
5044 req->fileFlags |= FsOpenReq::OM_DIRECT;
5045 FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
5046 req->auto_sync_size = c_defaults.m_disk_synch_size;
5048 TablePtr tabPtr;
5049 FragmentPtr fragPtr;
5051 ndbrequire(ptr.p->tables.first(tabPtr));
5052 tabPtr.p->fragments.getPtr(fragPtr, 0);
5055 * Lcp file
5057 BackupFilePtr filePtr LINT_SET_PTR;
5058 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5059 ndbrequire(filePtr.p->m_flags == 0);
5060 filePtr.p->m_flags |= BackupFile::BF_OPENING;
5061 filePtr.p->tableId = RNIL; // Will force init
5062 req->userPointer = filePtr.i;
5063 FsOpenReq::setVersion(req->fileNumber, 5);
5064 FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
5065 FsOpenReq::v5_setLcpNo(req->fileNumber, fragPtr.p->lcp_no);
5066 FsOpenReq::v5_setTableId(req->fileNumber, tabPtr.p->tableId);
5067 FsOpenReq::v5_setFragmentId(req->fileNumber, fragPtr.p->fragmentId);
5068 sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
5071 void
5072 Backup::lcp_open_file_done(Signal* signal, BackupRecordPtr ptr)
5074 TablePtr tabPtr;
5075 FragmentPtr fragPtr;
5077 ndbrequire(ptr.p->tables.first(tabPtr));
5078 tabPtr.p->fragments.getPtr(fragPtr, 0);
5080 BackupFilePtr filePtr LINT_SET_PTR;
5081 c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
5082 ndbrequire(filePtr.p->m_flags ==
5083 (BackupFile::BF_OPEN | BackupFile::BF_LCP_META));
5084 filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
5086 ptr.p->slaveState.setState(STARTED);
5088 LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtrSend();
5089 conf->senderData = ptr.p->clientData;
5090 conf->senderRef = reference();
5091 conf->tableId = tabPtr.p->tableId;
5092 conf->fragmentId = fragPtr.p->fragmentId;
5093 sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_CONF,
5094 signal, LcpPrepareConf::SignalLength, JBB);
5097 * Start file thread
5099 filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
5101 signal->theData[0] = BackupContinueB::START_FILE_THREAD;
5102 signal->theData[1] = filePtr.i;
5103 signal->theData[2] = __LINE__;
5104 sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
5107 void
5108 Backup::execEND_LCPREQ(Signal* signal)
5110 EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
5112 BackupRecordPtr ptr LINT_SET_PTR;
5113 c_backupPool.getPtr(ptr, req->backupPtr);
5114 ndbrequire(ptr.p->backupId == req->backupId);
5116 BackupFilePtr filePtr LINT_SET_PTR;
5117 ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
5118 ndbrequire(filePtr.p->m_flags == 0);
5120 if (!ptr.p->tables.isEmpty())
5122 jam();
5123 ndbrequire(ptr.p->errorCode);
5124 TablePtr tabPtr;
5125 ptr.p->tables.first(tabPtr);
5126 tabPtr.p->attributes.release();
5127 tabPtr.p->fragments.release();
5128 ptr.p->tables.release();
5129 ptr.p->errorCode = 0;
5132 ptr.p->errorCode = 0;
5133 ptr.p->slaveState.setState(CLEANING);
5134 ptr.p->slaveState.setState(INITIAL);
5135 ptr.p->slaveState.setState(DEFINING);
5136 ptr.p->slaveState.setState(DEFINED);
5138 EndLcpConf* conf= (EndLcpConf*)signal->getDataPtr();
5139 conf->senderData = ptr.p->clientData;
5140 conf->senderRef = reference();
5141 sendSignal(ptr.p->masterRef, GSN_END_LCPCONF,
5142 signal, EndLcpConf::SignalLength, JBB);