1
/* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include "Restore.hpp"
19
#include <OutputStream.hpp>
20
#include <Bitmask.hpp>
22
#include <AttributeHeader.hpp>
23
#include <trigger_definitions.h>
24
#include <SimpleProperties.hpp>
25
#include <signaldata/DictTabInfo.hpp>
26
#include <ndb_limits.h>
27
#include <NdbAutoPtr.hpp>
29
#include "../../../../sql/ha_ndbcluster_tables.h"
30
extern NdbRecordPrintFormat g_ndbrecord_print_format;
32
Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data
33
Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
34
Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
37
BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Uint32 arraySize){
44
arraySize = attr_desc->arraySize;
47
switch(attr_desc->size){
52
for(i = 0; i<arraySize; i++){
53
attr_data->u_int16_value[i] = Twiddle16(attr_data->u_int16_value[i]);
57
for(i = 0; i<arraySize; i++){
58
attr_data->u_int32_value[i] = Twiddle32(attr_data->u_int32_value[i]);
62
for(i = 0; i<arraySize; i++){
64
char* p = (char*)&attr_data->u_int64_value[i];
66
memcpy(&x, p, sizeof(Uint64));
68
memcpy(p, &x, sizeof(Uint64));
77
FilteredNdbOut err(* new FileOutputStream(stderr), 0, 0);
78
FilteredNdbOut info(* new FileOutputStream(stdout), 1, 1);
79
FilteredNdbOut debug(* new FileOutputStream(stdout), 2, 0);
81
// To decide in what byte order data is
82
const Uint32 magicByteOrder = 0x12345678;
83
const Uint32 swappedMagicByteOrder = 0x78563412;
85
RestoreMetaData::RestoreMetaData(const char* path, Uint32 nodeId, Uint32 bNo) {
87
debug << "RestoreMetaData constructor" << endl;
88
setCtlFile(nodeId, bNo, path);
91
RestoreMetaData::~RestoreMetaData(){
92
for(Uint32 i= 0; i < allTables.size(); i++)
94
TableS *table = allTables[i];
95
for(Uint32 j= 0; j < table->m_fragmentInfo.size(); j++)
96
delete table->m_fragmentInfo[j];
103
RestoreMetaData::getTable(Uint32 tableId) const {
104
for(Uint32 i= 0; i < allTables.size(); i++)
105
if(allTables[i]->getTableId() == tableId)
111
RestoreMetaData::getStopGCP() const {
116
RestoreMetaData::loadContent()
118
Uint32 noOfTables = readMetaTableList();
119
if(noOfTables == 0) {
122
for(Uint32 i = 0; i<noOfTables; i++){
123
if(!readMetaTableDesc()){
127
if (! markSysTables())
132
if(!readFragmentInfo())
138
RestoreMetaData::readMetaTableList() {
140
Uint32 sectionInfo[2];
142
if (buffer_read(§ionInfo, sizeof(sectionInfo), 1) != 1){
143
err << "readMetaTableList read header error" << endl;
146
sectionInfo[0] = ntohl(sectionInfo[0]);
147
sectionInfo[1] = ntohl(sectionInfo[1]);
149
const Uint32 tabCount = sectionInfo[1] - 2;
152
if (buffer_get_ptr(&tmp, 4, tabCount) != tabCount){
153
err << "readMetaTableList read tabCount error" << endl;
161
RestoreMetaData::readMetaTableDesc() {
163
Uint32 sectionInfo[3];
165
// Read section header
166
Uint32 sz = sizeof(sectionInfo) >> 2;
167
if (m_fileHeader.NdbVersion < NDBD_ROWID_VERSION)
170
sectionInfo[2] = htonl(DictTabInfo::UserTable);
172
if (buffer_read(§ionInfo, 4*sz, 1) != 1){
173
err << "readMetaTableDesc read header error" << endl;
176
sectionInfo[0] = ntohl(sectionInfo[0]);
177
sectionInfo[1] = ntohl(sectionInfo[1]);
178
sectionInfo[2] = ntohl(sectionInfo[2]);
180
assert(sectionInfo[0] == BackupFormat::TABLE_DESCRIPTION);
182
// Read dictTabInfo buffer
183
const Uint32 len = (sectionInfo[1] - sz);
185
if (buffer_get_ptr(&ptr, 4, len) != len){
186
err << "readMetaTableDesc read error" << endl;
191
DictObject obj = { sectionInfo[2], 0 };
192
switch(obj.m_objType){
193
case DictTabInfo::SystemTable:
194
case DictTabInfo::UserTable:
195
case DictTabInfo::UniqueHashIndex:
196
case DictTabInfo::OrderedIndex:
197
return parseTableDescriptor((Uint32*)ptr, len);
199
case DictTabInfo::Tablespace:
201
NdbDictionary::Tablespace * dst = new NdbDictionary::Tablespace;
203
NdbDictInterface::parseFilegroupInfo(NdbTablespaceImpl::getImpl(* dst),
208
debug << hex << obj.m_objPtr << " "
209
<< dec << dst->getObjectId() << " " << dst->getName() << endl;
212
case DictTabInfo::LogfileGroup:
214
NdbDictionary::LogfileGroup * dst = new NdbDictionary::LogfileGroup;
216
NdbDictInterface::parseFilegroupInfo(NdbLogfileGroupImpl::getImpl(* dst),
221
debug << hex << obj.m_objPtr << " "
222
<< dec << dst->getObjectId() << " " << dst->getName() << endl;
225
case DictTabInfo::Datafile:
227
NdbDictionary::Datafile * dst = new NdbDictionary::Datafile;
229
NdbDictInterface::parseFileInfo(NdbDatafileImpl::getImpl(* dst),
234
debug << hex << obj.m_objPtr << " "
235
<< dec << dst->getObjectId() << " " << dst->getPath() << endl;
238
case DictTabInfo::Undofile:
240
NdbDictionary::Undofile * dst = new NdbDictionary::Undofile;
242
NdbDictInterface::parseFileInfo(NdbUndofileImpl::getImpl(* dst),
247
debug << hex << obj.m_objPtr << " "
248
<< dec << dst->getObjectId() << " " << dst->getPath() << endl;
252
err << "Unsupported table type!! " << sectionInfo[2] << endl;
257
err << "Unable to parse dict info..."
258
<< sectionInfo[2] << " " << errcode << endl;
263
* DD objects need to be sorted...
265
for(Uint32 i = 0; i<m_objects.size(); i++)
267
switch(sectionInfo[2]){
268
case DictTabInfo::Tablespace:
269
if (DictTabInfo::isFile(m_objects[i].m_objType))
271
m_objects.push(obj, i);
275
case DictTabInfo::LogfileGroup:
277
if (DictTabInfo::isFile(m_objects[i].m_objType) ||
278
m_objects[i].m_objType == DictTabInfo::Tablespace)
280
m_objects.push(obj, i);
286
m_objects.push_back(obj);
290
m_objects.push_back(obj);
297
RestoreMetaData::markSysTables()
300
for (i = 0; i < getNoOfTables(); i++) {
301
TableS* table = allTables[i];
302
table->m_local_id = i;
303
const char* tableName = table->getTableName();
304
if ( // XXX should use type
305
strcmp(tableName, "SYSTAB_0") == 0 ||
306
strcmp(tableName, "NDB$EVENTS_0") == 0 ||
307
strcmp(tableName, "sys/def/SYSTAB_0") == 0 ||
308
strcmp(tableName, "sys/def/NDB$EVENTS_0") == 0 ||
310
The following is for old MySQL versions,
311
before we changed the database name of the tables from
312
"cluster_replication" -> "cluster" -> "mysql"
314
strcmp(tableName, "cluster_replication/def/" OLD_NDB_APPLY_TABLE) == 0 ||
315
strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_APPLY_TABLE) == 0 ||
316
strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_SCHEMA_TABLE) == 0 ||
317
strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 ||
318
strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 )
320
table->isSysTable = true;
322
for (i = 0; i < getNoOfTables(); i++) {
323
TableS* blobTable = allTables[i];
324
const char* blobTableName = blobTable->getTableName();
325
// yet another match blob
328
cnt = sscanf(blobTableName, "%[^/]/%[^/]/NDB$BLOB_%d_%d",
329
buf, buf, &id1, &id2);
332
for (j = 0; j < getNoOfTables(); j++) {
333
TableS* table = allTables[j];
334
if (table->getTableId() == (Uint32) id1) {
335
if (table->isSysTable)
336
blobTable->isSysTable = true;
337
blobTable->m_main_table = table;
341
if (j == getNoOfTables()) {
342
err << "Restore: Bad primary table id in " << blobTableName << endl;
351
RestoreMetaData::readGCPEntry() {
355
BackupFormat::CtlFile::GCPEntry * dst =
356
(BackupFormat::CtlFile::GCPEntry *)&data[0];
358
if(buffer_read(dst, 4, 4) != 4){
359
err << "readGCPEntry read error" << endl;
363
dst->SectionType = ntohl(dst->SectionType);
364
dst->SectionLength = ntohl(dst->SectionLength);
366
if(dst->SectionType != BackupFormat::GCP_ENTRY){
367
err << "readGCPEntry invalid format" << endl;
371
dst->StartGCP = ntohl(dst->StartGCP);
372
dst->StopGCP = ntohl(dst->StopGCP);
374
m_startGCP = dst->StartGCP;
375
m_stopGCP = dst->StopGCP;
380
RestoreMetaData::readFragmentInfo()
382
BackupFormat::CtlFile::FragmentInfo fragInfo;
384
Uint32 tableId = RNIL;
386
while (buffer_read(&fragInfo, 4, 2) == 2)
388
fragInfo.SectionType = ntohl(fragInfo.SectionType);
389
fragInfo.SectionLength = ntohl(fragInfo.SectionLength);
391
if (fragInfo.SectionType != BackupFormat::FRAGMENT_INFO)
393
err << "readFragmentInfo invalid section type: " <<
394
fragInfo.SectionType << endl;
398
if (buffer_read(&fragInfo.TableId, (fragInfo.SectionLength-2)*4, 1) != 1)
400
err << "readFragmentInfo invalid section length: " <<
401
fragInfo.SectionLength << endl;
405
fragInfo.TableId = ntohl(fragInfo.TableId);
406
if (fragInfo.TableId != tableId)
408
tableId = fragInfo.TableId;
409
table = getTable(tableId);
412
FragmentInfo * tmp = new FragmentInfo;
413
tmp->fragmentNo = ntohl(fragInfo.FragmentNo);
414
tmp->noOfRecords = ntohl(fragInfo.NoOfRecordsLow) +
415
(((Uint64)ntohl(fragInfo.NoOfRecordsHigh)) << 32);
416
tmp->filePosLow = ntohl(fragInfo.FilePosLow);
417
tmp->filePosHigh = ntohl(fragInfo.FilePosHigh);
419
table->m_fragmentInfo.push_back(tmp);
420
table->m_noOfRecords += tmp->noOfRecords;
425
TableS::TableS(Uint32 version, NdbTableImpl* tableImpl)
426
: m_dictTable(tableImpl)
428
m_dictTable = tableImpl;
429
m_noOfNullable = m_nullBitmaskSize = 0;
430
m_auto_val_id= ~(Uint32)0;
433
backupVersion = version;
437
for (int i = 0; i < tableImpl->getNoOfColumns(); i++)
438
createAttr(tableImpl->getColumn(i));
443
for (Uint32 i= 0; i < allAttributesDesc.size(); i++)
444
delete allAttributesDesc[i];
448
// Parse dictTabInfo buffer and pushback to to vector storage
450
RestoreMetaData::parseTableDescriptor(const Uint32 * data, Uint32 len)
452
NdbTableImpl* tableImpl = 0;
453
int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len, false,
454
m_fileHeader.NdbVersion);
457
err << "parseTableInfo " << " failed" << endl;
463
debug << "parseTableInfo " << tableImpl->getName() << " done" << endl;
464
TableS * table = new TableS(m_fileHeader.NdbVersion, tableImpl);
469
debug << "Parsed table id " << table->getTableId() << endl;
470
debug << "Parsed table #attr " << table->getNoOfAttributes() << endl;
471
debug << "Parsed table schema version not used " << endl;
473
debug << "Pushing table " << table->getTableName() << endl;
474
debug << " with " << table->getNoOfAttributes() << " attributes" << endl;
476
allTables.push_back(table);
482
RestoreDataIterator::RestoreDataIterator(const RestoreMetaData & md, void (* _free_data_callback)())
483
: BackupFile(_free_data_callback), m_metaData(md)
485
debug << "RestoreDataIterator constructor" << endl;
489
TupleS & TupleS::operator=(const TupleS& tuple)
491
prepareRecord(*tuple.m_currentTable);
494
memcpy(allAttrData, tuple.allAttrData, getNoOfAttributes()*sizeof(AttributeData));
498
int TupleS::getNoOfAttributes() const {
499
if (m_currentTable == 0)
501
return m_currentTable->getNoOfAttributes();
504
TableS * TupleS::getTable() const {
505
return m_currentTable;
508
const AttributeDesc * TupleS::getDesc(int i) const {
509
return m_currentTable->allAttributesDesc[i];
512
AttributeData * TupleS::getData(int i) const{
513
return &(allAttrData[i]);
517
TupleS::prepareRecord(TableS & tab){
519
if (getNoOfAttributes() == tab.getNoOfAttributes())
521
m_currentTable = &tab;
524
delete [] allAttrData;
528
allAttrData = new AttributeData[tab.getNoOfAttributes()];
529
if (allAttrData == 0)
532
m_currentTable = &tab;
538
RestoreDataIterator::readTupleData(Uint32 *buf_ptr, Uint32 *ptr,
541
while (ptr + 2 < buf_ptr + dataLength)
543
typedef BackupFormat::DataFile::VariableData VarData;
544
VarData * data = (VarData *)ptr;
545
Uint32 sz = ntohl(data->Sz);
546
Uint32 attrId = ntohl(data->Id); // column_no
548
AttributeData * attr_data = m_tuple.getData(attrId);
549
const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
551
// just a reminder - remove when backwards compat implemented
552
if (m_currentTable->backupVersion < MAKE_VERSION(5,1,3) &&
553
attr_desc->m_column->getNullable())
555
const Uint32 ind = attr_desc->m_nullBitIndex;
556
if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize,
559
attr_data->null = true;
560
attr_data->void_value = NULL;
565
if (m_currentTable->backupVersion < MAKE_VERSION(5,1,3))
570
attr_data->null = false;
571
attr_data->void_value = &data->Data[0];
572
attr_data->size = sz;
574
//if (m_currentTable->getTableId() >= 2) { ndbout << "var off=" << ptr-buf_ptr << " attrId=" << attrId << endl; }
579
const Uint32 arraySize = sz / (attr_desc->size / 8);
580
assert(arraySize <= attr_desc->arraySize);
582
//convert the length of blob(v1) and text(v1)
584
&& (attr_desc->m_column->getType() == NdbDictionary::Column::Blob
585
|| attr_desc->m_column->getType() == NdbDictionary::Column::Text)
586
&& attr_desc->m_column->getArrayType() == NdbDictionary::Column::ArrayTypeFixed)
588
char* p = (char*)&attr_data->u_int64_value[0];
590
memcpy(&x, p, sizeof(Uint64));
592
memcpy(p, &x, sizeof(Uint64));
595
//convert datetime type
597
&& attr_desc->m_column->getType() == NdbDictionary::Column::Datetime)
599
char* p = (char*)&attr_data->u_int64_value[0];
601
memcpy(&x, p, sizeof(Uint64));
603
memcpy(p, &x, sizeof(Uint64));
606
if(!Twiddle(attr_desc, attr_data, attr_desc->arraySize))
611
ptr += ((sz + 3) >> 2) + 2;
614
assert(ptr == buf_ptr + dataLength);
620
RestoreDataIterator::getNextTuple(int & res)
622
Uint32 dataLength = 0;
623
// Read record length
624
if (buffer_read(&dataLength, sizeof(dataLength), 1) != 1){
625
err << "getNextTuple:Error reading length of data part" << endl;
630
// Convert length from network byte order
631
dataLength = ntohl(dataLength);
632
const Uint32 dataLenBytes = 4 * dataLength;
634
if (dataLength == 0) {
635
// Zero length for last tuple
636
// End of this data fragment
637
debug << "End of fragment" << endl;
644
if (buffer_get_ptr(&_buf_ptr, 1, dataLenBytes) != dataLenBytes) {
645
err << "getNextTuple:Read error: " << endl;
650
//if (m_currentTable->getTableId() >= 2) { for (uint ii=0; ii<dataLenBytes; ii+=4) ndbout << "*" << hex << *(Uint32*)( (char*)_buf_ptr+ii ); ndbout << endl; }
652
Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr;
653
ptr += m_currentTable->m_nullBitmaskSize;
655
for(i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
656
assert(ptr < buf_ptr + dataLength);
658
const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId;
660
AttributeData * attr_data = m_tuple.getData(attrId);
661
const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
663
const Uint32 sz = attr_desc->getSizeInWords();
665
attr_data->null = false;
666
attr_data->void_value = ptr;
667
attr_data->size = 4*sz;
669
if(!Twiddle(attr_desc, attr_data))
677
for(i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
678
assert(ptr < buf_ptr + dataLength);
680
const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId;
682
AttributeData * attr_data = m_tuple.getData(attrId);
683
const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
685
const Uint32 sz = attr_desc->getSizeInWords();
687
attr_data->null = false;
688
attr_data->void_value = ptr;
689
attr_data->size = 4*sz;
691
//if (m_currentTable->getTableId() >= 2) { ndbout << "fix i=" << i << " off=" << ptr-buf_ptr << " attrId=" << attrId << endl; }
693
&& attr_desc->m_column->getType() == NdbDictionary::Column::Timestamp)
694
attr_data->u_int32_value[0] = Twiddle32(attr_data->u_int32_value[0]);
696
if(!Twiddle(attr_desc, attr_data))
706
for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
707
const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
709
AttributeData * attr_data = m_tuple.getData(attrId);
711
attr_data->null = true;
712
attr_data->void_value = NULL;
715
if ((res = readTupleData(buf_ptr, ptr, dataLength)))
721
} // RestoreDataIterator::getNextTuple
723
BackupFile::BackupFile(void (* _free_data_callback)())
724
: free_data_callback(_free_data_callback)
730
m_buffer_sz = 64*1024;
731
m_buffer = malloc(m_buffer_sz);
732
m_buffer_ptr = m_buffer;
733
m_buffer_data_left = 0;
736
BackupFile::~BackupFile(){
744
BackupFile::openFile(){
750
m_file = fopen(m_fileName, "r");
754
Uint32 BackupFile::buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
756
Uint32 sz = size*nmemb;
757
if (sz > m_buffer_data_left) {
759
if (free_data_callback)
760
(*free_data_callback)();
762
memcpy(m_buffer, m_buffer_ptr, m_buffer_data_left);
764
size_t r = fread(((char *)m_buffer) + m_buffer_data_left, 1, m_buffer_sz - m_buffer_data_left, m_file);
765
m_buffer_data_left += r;
766
m_buffer_ptr = m_buffer;
768
if (sz > m_buffer_data_left)
769
sz = size * (m_buffer_data_left / size);
772
*p_buf_ptr = m_buffer_ptr;
776
Uint32 BackupFile::buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
778
Uint32 r = buffer_get_ptr_ahead(p_buf_ptr, size, nmemb);
780
m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
781
m_buffer_data_left -= (r*size);
786
Uint32 BackupFile::buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb)
789
Uint32 r = buffer_get_ptr_ahead(&buf_ptr, size, nmemb);
790
memcpy(ptr, buf_ptr, r*size);
795
Uint32 BackupFile::buffer_read(void *ptr, Uint32 size, Uint32 nmemb)
798
Uint32 r = buffer_get_ptr(&buf_ptr, size, nmemb);
799
memcpy(ptr, buf_ptr, r*size);
805
BackupFile::setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path){
807
m_expectedFileHeader.BackupId = backupId;
808
m_expectedFileHeader.FileType = BackupFormat::CTL_FILE;
810
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
811
BaseString::snprintf(name, sz, "BACKUP-%d.%d.ctl", backupId, nodeId);
816
BackupFile::setDataFile(const BackupFile & bf, Uint32 no){
817
m_nodeId = bf.m_nodeId;
818
m_expectedFileHeader = bf.m_fileHeader;
819
m_expectedFileHeader.FileType = BackupFormat::DATA_FILE;
821
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
822
BaseString::snprintf(name, sz, "BACKUP-%d-%d.%d.Data",
823
m_expectedFileHeader.BackupId, no, m_nodeId);
824
setName(bf.m_path, name);
828
BackupFile::setLogFile(const BackupFile & bf, Uint32 no){
829
m_nodeId = bf.m_nodeId;
830
m_expectedFileHeader = bf.m_fileHeader;
831
m_expectedFileHeader.FileType = BackupFormat::LOG_FILE;
833
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
834
BaseString::snprintf(name, sz, "BACKUP-%d.%d.log",
835
m_expectedFileHeader.BackupId, m_nodeId);
836
setName(bf.m_path, name);
840
BackupFile::setName(const char * p, const char * n){
841
const Uint32 sz = sizeof(m_path);
842
if(p != 0 && strlen(p) > 0){
843
if(p[strlen(p)-1] == '/'){
844
BaseString::snprintf(m_path, sz, "%s", p);
846
BaseString::snprintf(m_path, sz, "%s%s", p, "/");
852
BaseString::snprintf(m_fileName, sizeof(m_fileName), "%s%s", m_path, n);
853
debug << "Filename = " << m_fileName << endl;
857
BackupFile::readHeader(){
862
if(buffer_read(&m_fileHeader, sizeof(m_fileHeader), 1) != 1){
863
err << "readDataFileHeader: Error reading header" << endl;
867
// Convert from network to host byte order for platform compatibility
868
m_fileHeader.NdbVersion = ntohl(m_fileHeader.NdbVersion);
869
m_fileHeader.SectionType = ntohl(m_fileHeader.SectionType);
870
m_fileHeader.SectionLength = ntohl(m_fileHeader.SectionLength);
871
m_fileHeader.FileType = ntohl(m_fileHeader.FileType);
872
m_fileHeader.BackupId = ntohl(m_fileHeader.BackupId);
873
m_fileHeader.BackupKey_0 = ntohl(m_fileHeader.BackupKey_0);
874
m_fileHeader.BackupKey_1 = ntohl(m_fileHeader.BackupKey_1);
876
debug << "FileHeader: " << m_fileHeader.Magic << " " <<
877
m_fileHeader.NdbVersion << " " <<
878
m_fileHeader.SectionType << " " <<
879
m_fileHeader.SectionLength << " " <<
880
m_fileHeader.FileType << " " <<
881
m_fileHeader.BackupId << " " <<
882
m_fileHeader.BackupKey_0 << " " <<
883
m_fileHeader.BackupKey_1 << " " <<
884
m_fileHeader.ByteOrder << endl;
886
debug << "ByteOrder is " << m_fileHeader.ByteOrder << endl;
887
debug << "magicByteOrder is " << magicByteOrder << endl;
889
if (m_fileHeader.FileType != m_expectedFileHeader.FileType){
893
// Check for BackupFormat::FileHeader::ByteOrder if swapping is needed
894
if (m_fileHeader.ByteOrder == magicByteOrder) {
895
m_hostByteOrder = true;
896
} else if (m_fileHeader.ByteOrder == swappedMagicByteOrder){
897
m_hostByteOrder = false;
903
} // BackupFile::readHeader
906
BackupFile::validateFooter(){
910
bool RestoreDataIterator::readFragmentHeader(int & ret, Uint32 *fragmentId)
912
BackupFormat::DataFile::FragmentHeader Header;
914
debug << "RestoreDataIterator::getNextFragment" << endl;
918
/* read first part of header */
919
if (buffer_read(&Header, 8, 1) != 1)
925
/* skip if EMPTY_ENTRY */
926
Header.SectionType = ntohl(Header.SectionType);
927
Header.SectionLength = ntohl(Header.SectionLength);
928
if (Header.SectionType == BackupFormat::EMPTY_ENTRY)
931
buffer_get_ptr(&tmp, Header.SectionLength*4-8, 1);
936
/* read rest of header */
937
if (buffer_read(((char*)&Header)+8, sizeof(Header)-8, 1) != 1)
942
Header.TableId = ntohl(Header.TableId);
943
Header.FragmentNo = ntohl(Header.FragmentNo);
944
Header.ChecksumType = ntohl(Header.ChecksumType);
946
debug << "FragmentHeader: " << Header.SectionType
947
<< " " << Header.SectionLength
948
<< " " << Header.TableId
949
<< " " << Header.FragmentNo
950
<< " " << Header.ChecksumType << endl;
952
m_currentTable = m_metaData.getTable(Header.TableId);
953
if(m_currentTable == 0){
958
if(!m_tuple.prepareRecord(*m_currentTable))
965
info << "_____________________________________________________" << endl
966
<< "Processing data in table: " << m_currentTable->getTableName()
967
<< "(" << Header.TableId << ") fragment "
968
<< Header.FragmentNo << endl;
972
*fragmentId = Header.FragmentNo;
974
} // RestoreDataIterator::getNextFragment
978
RestoreDataIterator::validateFragmentFooter() {
979
BackupFormat::DataFile::FragmentFooter footer;
981
if (buffer_read(&footer, sizeof(footer), 1) != 1){
982
err << "getFragmentFooter:Error reading fragment footer" << endl;
986
// TODO: Handle footer, nothing yet
987
footer.SectionType = ntohl(footer.SectionType);
988
footer.SectionLength = ntohl(footer.SectionLength);
989
footer.TableId = ntohl(footer.TableId);
990
footer.FragmentNo = ntohl(footer.FragmentNo);
991
footer.NoOfRecords = ntohl(footer.NoOfRecords);
992
footer.Checksum = ntohl(footer.Checksum);
994
assert(m_count == footer.NoOfRecords);
997
} // RestoreDataIterator::getFragmentFooter
999
AttributeDesc::AttributeDesc(NdbDictionary::Column *c)
1002
size = 8*NdbColumnImpl::getImpl(* c).m_attrSize;
1003
arraySize = NdbColumnImpl::getImpl(* c).m_arraySize;
1006
void TableS::createAttr(NdbDictionary::Column *column)
1008
AttributeDesc * d = new AttributeDesc(column);
1010
ndbout_c("Restore: Failed to allocate memory");
1013
d->attrId = allAttributesDesc.size();
1014
allAttributesDesc.push_back(d);
1016
if (d->m_column->getAutoIncrement())
1017
m_auto_val_id= d->attrId;
1019
if(d->m_column->getPrimaryKey() && backupVersion <= MAKE_VERSION(4,1,7))
1021
m_fixedKeys.push_back(d);
1025
if (d->m_column->getArrayType() == NDB_ARRAYTYPE_FIXED &&
1026
! d->m_column->getNullable())
1028
m_fixedAttribs.push_back(d);
1032
// just a reminder - does not solve backwards compat
1033
if (backupVersion < MAKE_VERSION(5,1,3))
1035
d->m_nullBitIndex = m_noOfNullable;
1037
m_nullBitmaskSize = (m_noOfNullable + 31) / 32;
1039
m_variableAttribs.push_back(d);
1040
} // TableS::createAttr
1042
Uint16 Twiddle16(Uint16 in)
1046
retVal = ((in & 0xFF00) >> 8) |
1047
((in & 0x00FF) << 8);
1052
Uint32 Twiddle32(Uint32 in)
1056
retVal = ((in & 0x000000FF) << 24) |
1057
((in & 0x0000FF00) << 8) |
1058
((in & 0x00FF0000) >> 8) |
1059
((in & 0xFF000000) >> 24);
1064
Uint64 Twiddle64(Uint64 in)
1069
((in & (Uint64)0x00000000000000FFLL) << 56) |
1070
((in & (Uint64)0x000000000000FF00LL) << 40) |
1071
((in & (Uint64)0x0000000000FF0000LL) << 24) |
1072
((in & (Uint64)0x00000000FF000000LL) << 8) |
1073
((in & (Uint64)0x000000FF00000000LL) >> 8) |
1074
((in & (Uint64)0x0000FF0000000000LL) >> 24) |
1075
((in & (Uint64)0x00FF000000000000LL) >> 40) |
1076
((in & (Uint64)0xFF00000000000000LL) >> 56);
1082
RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md)
1085
debug << "RestoreLog constructor" << endl;
1093
RestoreLogIterator::getNextLogEntry(int & res) {
1094
// Read record length
1095
const Uint32 stopGCP = m_metaData.getStopGCP();
1097
Uint32 triggerEvent;
1100
Uint32 attr_data_len;
1103
Uint32 *logEntryPtr;
1104
if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
1110
Uint32 data_len = sizeof(Uint32) + len*4;
1111
if (buffer_get_ptr((void **)(&logEntryPtr), 1, data_len) != data_len) {
1121
if (unlikely(m_metaData.getFileHeader().NdbVersion < NDBD_FRAGID_VERSION))
1124
FragId was introduced in LogEntry in version
1126
We set FragId to 0 in older versions (these versions
1127
do not support restore of user defined partitioned
1130
typedef BackupFormat::LogFile::LogEntry_no_fragid LogE_no_fragid;
1131
LogE_no_fragid * logE_no_fragid= (LogE_no_fragid *)logEntryPtr;
1132
tableId= ntohl(logE_no_fragid->TableId);
1133
triggerEvent= ntohl(logE_no_fragid->TriggerEvent);
1135
attr_data= &logE_no_fragid->Data[0];
1136
attr_data_len= len - ((offsetof(LogE_no_fragid, Data) >> 2) - 1);
1138
else /* normal case */
1140
typedef BackupFormat::LogFile::LogEntry LogE;
1141
LogE * logE= (LogE *)logEntryPtr;
1142
tableId= ntohl(logE->TableId);
1143
triggerEvent= ntohl(logE->TriggerEvent);
1144
frag_id= ntohl(logE->FragId);
1145
attr_data= &logE->Data[0];
1146
attr_data_len= len - ((offsetof(LogE, Data) >> 2) - 1);
1149
const bool hasGcp= (triggerEvent & 0x10000) != 0;
1150
triggerEvent &= 0xFFFF;
1153
// last attr_data is gci info
1155
m_last_gci = ntohl(*(attr_data + attr_data_len));
1157
} while(m_last_gci > stopGCP + 1);
1159
m_logEntry.m_table = m_metaData.getTable(tableId);
1160
switch(triggerEvent){
1161
case TriggerEvent::TE_INSERT:
1162
m_logEntry.m_type = LogEntry::LE_INSERT;
1164
case TriggerEvent::TE_UPDATE:
1165
m_logEntry.m_type = LogEntry::LE_UPDATE;
1167
case TriggerEvent::TE_DELETE:
1168
m_logEntry.m_type = LogEntry::LE_DELETE;
1175
const TableS * tab = m_logEntry.m_table;
1178
AttributeHeader * ah = (AttributeHeader *)attr_data;
1179
AttributeHeader *end = (AttributeHeader *)(attr_data + attr_data_len);
1181
m_logEntry.m_frag_id = frag_id;
1183
attr= m_logEntry.add_attr();
1185
ndbout_c("Restore: Failed to allocate memory");
1190
if(unlikely(!m_hostByteOrder))
1191
*(Uint32*)ah = Twiddle32(*(Uint32*)ah);
1193
attr->Desc = (* tab)[ah->getAttributeId()];
1194
assert(attr->Desc != 0);
1196
const Uint32 sz = ah->getDataSize();
1198
attr->Data.null = true;
1199
attr->Data.void_value = NULL;
1201
attr->Data.null = false;
1202
attr->Data.void_value = ah->getDataPtr();
1205
Twiddle(attr->Desc, &(attr->Data));
1216
operator<<(NdbOut& ndbout, const AttributeS& attr){
1217
const AttributeData & data = attr.Data;
1218
const AttributeDesc & desc = *(attr.Desc);
1222
ndbout << g_ndbrecord_print_format.null_string;
1226
NdbRecAttr tmprec(0);
1227
tmprec.setup(desc.m_column, 0);
1228
tmprec.receive_data((Uint32*)data.void_value, data.size);
1229
ndbrecattr_print_formatted(ndbout, tmprec, g_ndbrecord_print_format);
1236
operator<<(NdbOut& ndbout, const TupleS& tuple)
1238
for (int i = 0; i < tuple.getNoOfAttributes(); i++)
1241
ndbout << g_ndbrecord_print_format.fields_terminated_by;
1242
AttributeData * attr_data = tuple.getData(i);
1243
const AttributeDesc * attr_desc = tuple.getDesc(i);
1244
const AttributeS attr = {attr_desc, *attr_data};
1245
debug << i << " " << attr_desc->m_column->getName();
1253
operator<<(NdbOut& ndbout, const LogEntry& logE)
1257
case LogEntry::LE_INSERT:
1258
ndbout << "INSERT " << logE.m_table->getTableName() << " ";
1260
case LogEntry::LE_DELETE:
1261
ndbout << "DELETE " << logE.m_table->getTableName() << " ";
1263
case LogEntry::LE_UPDATE:
1264
ndbout << "UPDATE " << logE.m_table->getTableName() << " ";
1267
ndbout << "Unknown log entry type (not insert, delete or update)" ;
1270
for (Uint32 i= 0; i < logE.size();i++)
1272
const AttributeS * attr = logE[i];
1273
ndbout << attr->Desc->m_column->getName() << "=";
1275
if (i < (logE.size() - 1))
1284
operator<<(NdbOut& ndbout, const TableS & table){
1286
ndbout << (* (NDBT_Table*)table.m_dictTable) << endl;
1290
template class Vector<TableS*>;
1291
template class Vector<AttributeS*>;
1292
template class Vector<AttributeDesc*>;
1293
template class Vector<FragmentInfo*>;
1294
template class Vector<DictObject>;