MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Restore.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include "Restore.hpp"
19 #include <NdbTCP.h>
20 #include <NdbMem.h>
21 #include <OutputStream.hpp>
22 #include <Bitmask.hpp>
23 
24 #include <AttributeHeader.hpp>
25 #include <trigger_definitions.h>
26 #include <SimpleProperties.hpp>
27 #include <signaldata/DictTabInfo.hpp>
28 #include <ndb_limits.h>
29 #include <NdbAutoPtr.hpp>
30 #include "../src/ndbapi/NdbDictionaryImpl.hpp"
31 
32 #include "../../../../sql/ha_ndbcluster_tables.h"
33 extern NdbRecordPrintFormat g_ndbrecord_print_format;
34 extern bool ga_skip_unknown_objects;
35 extern bool ga_skip_broken_objects;
36 
37 Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data
38 Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
39 Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
40 
41 
42 /*
43  TwiddleUtil
44 
45  Utility class used when swapping byteorder
46  of one attribute in a table
47 
48 */
49 
50 class TwiddleUtil {
51  Uint32 m_twiddle_size;
52  Uint32 m_twiddle_array_size;
53 public:
54  TwiddleUtil(); // Not implemented
55  TwiddleUtil(const TwiddleUtil&); // Not implemented
56 
57  TwiddleUtil(const AttributeDesc * const attr_desc) {
58  const NdbDictionary::Column::Type attribute_type =
59  attr_desc->m_column->getType();
60 
61  switch(attribute_type){
63  // Datetime is stored as 8x8, should be twiddled as 64 bit
64  assert(attr_desc->size == 8);
65  assert(attr_desc->arraySize == 8);
66  m_twiddle_size = 64;
67  m_twiddle_array_size = 1;
68  break;
69 
71  // Timestamp is stored as 4x8, should be twiddled as 32 bit
72  assert(attr_desc->size == 8);
73  assert(attr_desc->arraySize == 4);
74  m_twiddle_size = 32;
75  m_twiddle_array_size = 1;
76  break;
77 
80  if (attr_desc->m_column->getArrayType() ==
81  NdbDictionary::Column::ArrayTypeFixed)
82  {
83  // Length of fixed size blob which is stored in first 64 bit's
84  // has to be twiddled, the remaining byte stream left as is
85  assert(attr_desc->size == 8);
86  assert(attr_desc->arraySize > 8);
87  m_twiddle_size = 64;
88  m_twiddle_array_size = 1;
89  break;
90  }
91  // Fallthrough for blob/text with ArrayTypeVar
92 
93  default:
94  // Default twiddling parameters
95  m_twiddle_size = attr_desc->size;
96  m_twiddle_array_size = attr_desc->arraySize;
97  break;
98  }
99 
100  assert(m_twiddle_array_size);
101  assert(m_twiddle_size);
102  }
103 
104  bool is_aligned (void* data_ptr) const {
105  switch (m_twiddle_size){
106  case 8:
107  // Always aligned
108  return true;
109  break;
110  case 16:
111  return ((((size_t)data_ptr) & 1) == 0);
112  break;
113  case 32:
114  return ((((size_t)data_ptr) & 3) == 0);
115  break;
116  case 64:
117  return ((((size_t)data_ptr) & 7) == 0);
118  break;
119  default:
120  abort();
121  break;
122  }
123  return false; // Never reached
124  }
125 
126  void twiddle_aligned(void* const data_ptr) const {
127  // Make sure the data pointer is properly aligned
128  assert(is_aligned(data_ptr));
129 
130  switch(m_twiddle_size){
131  case 8:
132  // Nothing to swap
133  break;
134  case 16:
135  {
136  Uint16* ptr = (Uint16*)data_ptr;
137  for (Uint32 i = 0; i < m_twiddle_array_size; i++){
138  *ptr = Twiddle16(*ptr);
139  ptr++;
140  }
141  break;
142  }
143  case 32:
144  {
145  Uint32* ptr = (Uint32*)data_ptr;
146  for (Uint32 i = 0; i < m_twiddle_array_size; i++){
147  *ptr = Twiddle32(*ptr);
148  ptr++;
149  }
150  break;
151  }
152  case 64:
153  {
154  Uint64* ptr = (Uint64*)data_ptr;
155  for (Uint32 i = 0; i < m_twiddle_array_size; i++){
156  *ptr = Twiddle64(*ptr);
157  ptr++;
158  }
159  break;
160  }
161  default:
162  abort();
163  } // switch
164  }
165 };
166 
167 
168 /*
169  BackupFile::twiddle_attribute
170 
171  Swap the byte order of one attribute whose data may or may not
172  be properly aligned for the current datatype
173 
174 */
175 
176 void
177 BackupFile::twiddle_atribute(const AttributeDesc * const attr_desc,
178  AttributeData* attr_data)
179 {
180  TwiddleUtil map(attr_desc);
181 
182  // Check if data is aligned properly
183  void* data_ptr = (char*)attr_data->void_value;
184  Uint32 data_sz = attr_desc->getSizeInBytes();
185  bool aligned= map.is_aligned(data_ptr);
186  if (!aligned)
187  {
188  // The pointer is not properly aligned, copy the data
189  // to aligned memory before twiddling
190  m_twiddle_buffer.assign(data_ptr, data_sz);
191  data_ptr = m_twiddle_buffer.get_data();
192  }
193 
194  // Swap the byteorder of the aligned data
195  map.twiddle_aligned(data_ptr);
196 
197  if (!aligned)
198  {
199  // Copy data back from aligned memory
200  memcpy(attr_data->void_value,
201  m_twiddle_buffer.get_data(),
202  data_sz);
203  }
204 }
205 
206 
207 /*
208  BackupFile::Twiddle
209 
210  Swap the byteorder for one attribute if it was stored
211  in different byteorder than current host
212 
213 */
214 
215 bool
216 BackupFile::Twiddle(const AttributeDesc * const attr_desc,
217  AttributeData* attr_data)
218 {
219  // Check parameters are not NULL
220  assert(attr_desc);
221  assert(attr_data);
222 
223  // Make sure there is data to fiddle with
224  assert(!attr_data->null);
225  assert(attr_data->void_value);
226 
227  if(unlikely(!m_hostByteOrder))
228  {
229  // The data file is not in host byte order, the
230  // attribute need byte order swapped
231  twiddle_atribute(attr_desc, attr_data);
232  }
233 #ifdef VM_TRACE
234  else
235  {
236  // Increase test converage in debug mode by doing
237  // a double byte order swap to prove that both ways work
238  twiddle_atribute(attr_desc, attr_data);
239  twiddle_atribute(attr_desc, attr_data);
240  }
241 #endif
242 
243  return true;
244 }
245 
246 
247 FilteredNdbOut err(* new FileOutputStream(stderr), 0, 0);
248 FilteredNdbOut info(* new FileOutputStream(stdout), 1, 1);
249 FilteredNdbOut debug(* new FileOutputStream(stdout), 2, 0);
250 
251 // To decide in what byte order data is
252 const Uint32 magicByteOrder = 0x12345678;
253 const Uint32 swappedMagicByteOrder = 0x78563412;
254 
255 RestoreMetaData::RestoreMetaData(const char* path, Uint32 nodeId, Uint32 bNo) {
256 
257  debug << "RestoreMetaData constructor" << endl;
258  setCtlFile(nodeId, bNo, path);
259 }
260 
261 RestoreMetaData::~RestoreMetaData(){
262  for(Uint32 i= 0; i < allTables.size(); i++)
263  {
264  TableS *table = allTables[i];
265  for(Uint32 j= 0; j < table->m_fragmentInfo.size(); j++)
266  delete table->m_fragmentInfo[j];
267  delete table;
268  }
269  allTables.clear();
270 }
271 
272 TableS *
273 RestoreMetaData::getTable(Uint32 tableId) const {
274  for(Uint32 i= 0; i < allTables.size(); i++)
275  if(allTables[i]->getTableId() == tableId)
276  return allTables[i];
277  return NULL;
278 }
279 
280 Uint32
281 RestoreMetaData::getStopGCP() const {
282  return m_stopGCP;
283 }
284 
285 int
286 RestoreMetaData::loadContent()
287 {
288  Uint32 noOfTables = readMetaTableList();
289  if(noOfTables == 0) {
290  return 1;
291  }
292  for(Uint32 i = 0; i<noOfTables; i++){
293  if(!readMetaTableDesc()){
294  return 0;
295  }
296  }
297  if (!markSysTables())
298  return 0;
299  if (!fixBlobs())
300  return 0;
301  if(!readGCPEntry())
302  return 0;
303 
304  if(!readFragmentInfo())
305  return 0;
306  return 1;
307 }
308 
309 Uint32
310 RestoreMetaData::readMetaTableList() {
311 
312  Uint32 sectionInfo[2];
313 
314  if (buffer_read(&sectionInfo, sizeof(sectionInfo), 1) != 1){
315  err << "readMetaTableList read header error" << endl;
316  return 0;
317  }
318  sectionInfo[0] = ntohl(sectionInfo[0]);
319  sectionInfo[1] = ntohl(sectionInfo[1]);
320 
321  const Uint32 tabCount = sectionInfo[1] - 2;
322 
323  void *tmp;
324  if (buffer_get_ptr(&tmp, 4, tabCount) != tabCount){
325  err << "readMetaTableList read tabCount error" << endl;
326  return 0;
327  }
328 
329  return tabCount;
330 }
331 
332 bool
333 RestoreMetaData::readMetaTableDesc() {
334 
335  Uint32 sectionInfo[3];
336 
337  // Read section header
338  Uint32 sz = sizeof(sectionInfo) >> 2;
339  if (m_fileHeader.NdbVersion < NDBD_ROWID_VERSION ||
340  isDrop6(m_fileHeader.NdbVersion))
341  {
342  sz = 2;
343  sectionInfo[2] = htonl(DictTabInfo::UserTable);
344  }
345  if (buffer_read(&sectionInfo, 4*sz, 1) != 1){
346  err << "readMetaTableDesc read header error" << endl;
347  return false;
348  } // if
349  sectionInfo[0] = ntohl(sectionInfo[0]);
350  sectionInfo[1] = ntohl(sectionInfo[1]);
351  sectionInfo[2] = ntohl(sectionInfo[2]);
352 
353  assert(sectionInfo[0] == BackupFormat::TABLE_DESCRIPTION);
354 
355  // Read dictTabInfo buffer
356  const Uint32 len = (sectionInfo[1] - sz);
357  void *ptr;
358  if (buffer_get_ptr(&ptr, 4, len) != len){
359  err << "readMetaTableDesc read error" << endl;
360  return false;
361  } // if
362 
363  int errcode = 0;
364  DictObject obj = { sectionInfo[2], 0 };
365  switch(obj.m_objType){
366  case DictTabInfo::SystemTable:
367  case DictTabInfo::UserTable:
368  case DictTabInfo::UniqueHashIndex:
369  case DictTabInfo::OrderedIndex:
370  return parseTableDescriptor((Uint32*)ptr, len);
371  break;
373  {
375  errcode =
376  NdbDictInterface::parseFilegroupInfo(NdbTablespaceImpl::getImpl(* dst),
377  (Uint32*)ptr, len);
378  if (errcode)
379  delete dst;
380  obj.m_objPtr = dst;
381  debug << hex << obj.m_objPtr << " "
382  << dec << dst->getObjectId() << " " << dst->getName() << endl;
383  break;
384  }
386  {
388  errcode =
389  NdbDictInterface::parseFilegroupInfo(NdbLogfileGroupImpl::getImpl(* dst),
390  (Uint32*)ptr, len);
391  if (errcode)
392  delete dst;
393  obj.m_objPtr = dst;
394  debug << hex << obj.m_objPtr << " "
395  << dec << dst->getObjectId() << " " << dst->getName() << endl;
396  break;
397  }
399  {
401  errcode =
402  NdbDictInterface::parseFileInfo(NdbDatafileImpl::getImpl(* dst),
403  (Uint32*)ptr, len);
404  if (errcode)
405  delete dst;
406  obj.m_objPtr = dst;
407  debug << hex << obj.m_objPtr << " "
408  << dec << dst->getObjectId() << " " << dst->getPath() << endl;
409  break;
410  }
412  {
414  errcode =
415  NdbDictInterface::parseFileInfo(NdbUndofileImpl::getImpl(* dst),
416  (Uint32*)ptr, len);
417  if (errcode)
418  delete dst;
419  obj.m_objPtr = dst;
420  debug << hex << obj.m_objPtr << " "
421  << dec << dst->getObjectId() << " " << dst->getPath() << endl;
422  break;
423  }
424  case DictTabInfo::HashMap:
425  {
427  errcode =
428  NdbDictInterface::parseHashMapInfo(NdbHashMapImpl::getImpl(* dst),
429  (Uint32*)ptr, len);
430  if (errcode)
431  delete dst;
432  obj.m_objPtr = dst;
433 
434  if (!m_hostByteOrder)
435  {
439  Vector<Uint32> values;
440  Uint32 len = dst->getMapLen();
441  Uint32 zero = 0;
442  values.fill(len - 1, zero);
443  dst->getMapValues(values.getBase(), values.size());
444  for (Uint32 i = 0; i<len; i++)
445  {
446  values[i] = Twiddle16(values[i]);
447  }
448  dst->setMap(values.getBase(), values.size());
449  }
450 
451  m_objects.push(obj, 0); // Put first
452  return true;
453  break;
454  }
455  default:
456  if (ga_skip_unknown_objects)
457  {
458  info << "Skipping schema object with unknown table type "
459  << sectionInfo[2] << endl;
460  return true;
461  }
462  else
463  {
464  err << "Unsupported table type!! " << sectionInfo[2] << endl;
465  return false;
466  }
467  }
468  if (errcode)
469  {
470  err << "Unable to parse dict info..."
471  << sectionInfo[2] << " " << errcode << endl;
472  return false;
473  }
474 
478  for(Uint32 i = 0; i<m_objects.size(); i++)
479  {
480  switch(sectionInfo[2]){
482  if (DictTabInfo::isFile(m_objects[i].m_objType))
483  {
484  m_objects.push(obj, i);
485  goto end;
486  }
487  break;
489  {
490  if (DictTabInfo::isFile(m_objects[i].m_objType) ||
491  m_objects[i].m_objType == DictTabInfo::Tablespace)
492  {
493  m_objects.push(obj, i);
494  goto end;
495  }
496  break;
497  }
498  default:
499  m_objects.push_back(obj);
500  goto end;
501  }
502  }
503  m_objects.push_back(obj);
504 
505 end:
506  return true;
507 }
508 
509 #define OLD_NDB_REP_DB "cluster"
510 #define OLD_NDB_APPLY_TABLE "apply_status"
511 #define OLD_NDB_SCHEMA_TABLE "schema"
512 
513 bool
514 RestoreMetaData::markSysTables()
515 {
516  Uint32 i;
517  for (i = 0; i < getNoOfTables(); i++) {
518  TableS* table = allTables[i];
519  table->m_local_id = i;
520  const char* tableName = table->getTableName();
521  if ( // XXX should use type
522  strcmp(tableName, "SYSTAB_0") == 0 ||
523  strcmp(tableName, "NDB$EVENTS_0") == 0 ||
524  strcmp(tableName, "sys/def/SYSTAB_0") == 0 ||
525  strcmp(tableName, "sys/def/NDB$EVENTS_0") == 0 ||
526  // index stats tables and indexes
527  strncmp(tableName, NDB_INDEX_STAT_PREFIX,
528  sizeof(NDB_INDEX_STAT_PREFIX)-1) == 0 ||
529  strstr(tableName, "/" NDB_INDEX_STAT_PREFIX) != 0 ||
530  /*
531  The following is for old MySQL versions,
532  before we changed the database name of the tables from
533  "cluster_replication" -> "cluster" -> "mysql"
534  */
535  strcmp(tableName, "cluster_replication/def/" OLD_NDB_APPLY_TABLE) == 0 ||
536  strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_APPLY_TABLE) == 0 ||
537  strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_SCHEMA_TABLE) == 0 ||
538  strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 ||
539  strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 )
540  {
541  table->m_isSysTable = true;
542  if (strcmp(tableName, "SYSTAB_0") == 0 ||
543  strcmp(tableName, "sys/def/SYSTAB_0") == 0)
544  table->m_isSYSTAB_0 = true;
545  }
546  }
547  for (i = 0; i < getNoOfTables(); i++) {
548  TableS* blobTable = allTables[i];
549  const char* blobTableName = blobTable->getTableName();
550  // yet another match blob
551  int cnt, id1, id2;
552  char buf[256];
553  cnt = sscanf(blobTableName, "%[^/]/%[^/]/NDB$BLOB_%d_%d",
554  buf, buf, &id1, &id2);
555  if (cnt == 4) {
556  Uint32 j;
557  for (j = 0; j < getNoOfTables(); j++) {
558  TableS* table = allTables[j];
559  if (table->getTableId() == (Uint32) id1) {
560  if (table->m_isSysTable)
561  blobTable->m_isSysTable = true;
562  blobTable->m_main_table = table;
563  blobTable->m_main_column_id = id2;
564  break;
565  }
566  }
567  if (j == getNoOfTables()) {
568  err << "Restore: Bad primary table id in " << blobTableName << endl;
569  return false;
570  }
571  }
572  }
573  return true;
574 }
575 
576 bool
577 RestoreMetaData::fixBlobs()
578 {
579  Uint32 i;
580  for (i = 0; i < getNoOfTables(); i++) {
581  TableS* table = allTables[i];
582  assert(table->m_dictTable != NULL);
583  NdbTableImpl& t = NdbTableImpl::getImpl(*table->m_dictTable);
584  const Uint32 noOfBlobs = t.m_noOfBlobs;
585  if (noOfBlobs == 0)
586  continue;
587  Uint32 n = 0;
588  Uint32 j;
589  for (j = 0; n < noOfBlobs; j++) {
590  NdbColumnImpl* c = t.getColumn(j);
591  assert(c != NULL);
592  if (!c->getBlobType())
593  continue;
594  // tinyblobs are counted in noOfBlobs...
595  n++;
596  if (c->getPartSize() == 0)
597  continue;
598  Uint32 k;
599  TableS* blobTable = NULL;
600  for (k = 0; k < getNoOfTables(); k++) {
601  TableS* tmp = allTables[k];
602  if (tmp->m_main_table == table &&
603  tmp->m_main_column_id == j) {
604  blobTable = tmp;
605  break;
606  }
607  }
608  if (blobTable == NULL)
609  {
610  table->m_broken = true;
611  /* Corrupt backup, has main table, but no blob table */
612  err << "Table " << table->m_dictTable->getName()
613  << " has blob column " << j << " ("
614  << c->m_name.c_str()
615  << ") with missing parts table in backup."
616  << endl;
617  if (ga_skip_broken_objects)
618  {
619  continue;
620  }
621  else
622  {
623  return false;
624  }
625  }
626  assert(blobTable->m_dictTable != NULL);
627  NdbTableImpl& bt = NdbTableImpl::getImpl(*blobTable->m_dictTable);
628  const char* colName = c->m_blobVersion == 1 ? "DATA" : "NDB$DATA";
629  const NdbColumnImpl* bc = bt.getColumn(colName);
630  assert(bc != NULL);
631  assert(c->m_storageType == NDB_STORAGETYPE_MEMORY);
632  c->m_storageType = bc->m_storageType;
633  }
634  }
635  return true;
636 }
637 
638 bool
639 RestoreMetaData::readGCPEntry() {
640 
642 
643  if(buffer_read(&dst, 1, sizeof(dst)) != sizeof(dst)){
644  err << "readGCPEntry read error" << endl;
645  return false;
646  }
647 
648  dst.SectionType = ntohl(dst.SectionType);
649  dst.SectionLength = ntohl(dst.SectionLength);
650 
651  if(dst.SectionType != BackupFormat::GCP_ENTRY){
652  err << "readGCPEntry invalid format" << endl;
653  return false;
654  }
655 
656  dst.StartGCP = ntohl(dst.StartGCP);
657  dst.StopGCP = ntohl(dst.StopGCP);
658 
659  m_startGCP = dst.StartGCP;
660  m_stopGCP = dst.StopGCP;
661  return true;
662 }
663 
664 bool
665 RestoreMetaData::readFragmentInfo()
666 {
668  TableS * table = 0;
669  Uint32 tableId = RNIL;
670 
671  while (buffer_read(&fragInfo, 4, 2) == 2)
672  {
673  fragInfo.SectionType = ntohl(fragInfo.SectionType);
674  fragInfo.SectionLength = ntohl(fragInfo.SectionLength);
675 
676  if (fragInfo.SectionType != BackupFormat::FRAGMENT_INFO)
677  {
678  err << "readFragmentInfo invalid section type: " <<
679  fragInfo.SectionType << endl;
680  return false;
681  }
682 
683  if (buffer_read(&fragInfo.TableId, (fragInfo.SectionLength-2)*4, 1) != 1)
684  {
685  err << "readFragmentInfo invalid section length: " <<
686  fragInfo.SectionLength << endl;
687  return false;
688  }
689 
690  fragInfo.TableId = ntohl(fragInfo.TableId);
691  if (fragInfo.TableId != tableId)
692  {
693  tableId = fragInfo.TableId;
694  table = getTable(tableId);
695  }
696 
697  FragmentInfo * tmp = new FragmentInfo;
698  tmp->fragmentNo = ntohl(fragInfo.FragmentNo);
699  tmp->noOfRecords = ntohl(fragInfo.NoOfRecordsLow) +
700  (((Uint64)ntohl(fragInfo.NoOfRecordsHigh)) << 32);
701  tmp->filePosLow = ntohl(fragInfo.FilePosLow);
702  tmp->filePosHigh = ntohl(fragInfo.FilePosHigh);
703 
704  table->m_fragmentInfo.push_back(tmp);
705  table->m_noOfRecords += tmp->noOfRecords;
706  }
707  return true;
708 }
709 
710 TableS::TableS(Uint32 version, NdbTableImpl* tableImpl)
711  : m_dictTable(tableImpl)
712 {
713  m_dictTable = tableImpl;
714  m_noOfNullable = m_nullBitmaskSize = 0;
715  m_auto_val_attrib = 0;
716  m_max_auto_val= 0;
717  m_noOfRecords= 0;
718  backupVersion = version;
719  m_isSysTable = false;
720  m_isSYSTAB_0 = false;
721  m_broken = false;
722  m_main_table = NULL;
723  m_main_column_id = ~(Uint32)0;
724 
725  for (int i = 0; i < tableImpl->getNoOfColumns(); i++)
726  createAttr(tableImpl->getColumn(i));
727 }
728 
729 TableS::~TableS()
730 {
731  for (Uint32 i= 0; i < allAttributesDesc.size(); i++)
732  {
733  if (allAttributesDesc[i]->parameter)
734  free(allAttributesDesc[i]->parameter);
735  delete allAttributesDesc[i];
736  }
737 }
738 
739 
740 // Parse dictTabInfo buffer and pushback to to vector storage
741 bool
742 RestoreMetaData::parseTableDescriptor(const Uint32 * data, Uint32 len)
743 {
744  NdbTableImpl* tableImpl = 0;
746  (&tableImpl, data, len, false,
747  isDrop6(m_fileHeader.NdbVersion) ? MAKE_VERSION(5,1,2) :
748  m_fileHeader.NdbVersion);
749 
750  if (ret != 0) {
751  err << "parseTableInfo " << " failed" << endl;
752  return false;
753  }
754  if(tableImpl == 0)
755  return false;
756 
757  debug << "parseTableInfo " << tableImpl->getName() << " done" << endl;
758  TableS * table = new TableS(m_fileHeader.NdbVersion, tableImpl);
759  if(table == NULL) {
760  return false;
761  }
762 
763  debug << "Parsed table id " << table->getTableId() << endl;
764  debug << "Parsed table #attr " << table->getNoOfAttributes() << endl;
765  debug << "Parsed table schema version not used " << endl;
766 
767  debug << "Pushing table " << table->getTableName() << endl;
768  debug << " with " << table->getNoOfAttributes() << " attributes" << endl;
769 
770  allTables.push_back(table);
771 
772  return true;
773 }
774 
775 // Constructor
776 RestoreDataIterator::RestoreDataIterator(const RestoreMetaData & md, void (* _free_data_callback)())
777  : BackupFile(_free_data_callback), m_metaData(md)
778 {
779  debug << "RestoreDataIterator constructor" << endl;
780  setDataFile(md, 0);
781 
782  m_bitfield_storage_len = 8192;
783  m_bitfield_storage_ptr = (Uint32*)malloc(4*m_bitfield_storage_len);
784  m_bitfield_storage_curr_ptr = m_bitfield_storage_ptr;
785  m_row_bitfield_len = 0;
786 }
787 
788 RestoreDataIterator::~RestoreDataIterator()
789 {
790  free_bitfield_storage();
791 }
792 
793 void
794 RestoreDataIterator::init_bitfield_storage(const NdbDictionary::Table* tab)
795 {
796  Uint32 len = 0;
797  for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
798  {
799  if (tab->getColumn(i)->getType() == NdbDictionary::Column::Bit)
800  {
801  len += (tab->getColumn(i)->getLength() + 31) >> 5;
802  }
803  }
804 
805  m_row_bitfield_len = len;
806 }
807 
808 void
809 RestoreDataIterator::reset_bitfield_storage()
810 {
811  m_bitfield_storage_curr_ptr = m_bitfield_storage_ptr;
812 }
813 
814 void
815 RestoreDataIterator::free_bitfield_storage()
816 {
817  if (m_bitfield_storage_ptr)
818  free(m_bitfield_storage_ptr);
819  m_bitfield_storage_ptr = 0;
820  m_bitfield_storage_curr_ptr = 0;
821  m_bitfield_storage_len = 0;
822 }
823 
824 Uint32
825 RestoreDataIterator::get_free_bitfield_storage() const
826 {
827 
828  return Uint32((m_bitfield_storage_ptr + m_bitfield_storage_len) -
829  m_bitfield_storage_curr_ptr);
830 }
831 
832 Uint32*
833 RestoreDataIterator::get_bitfield_storage(Uint32 len)
834 {
835  Uint32 * currptr = m_bitfield_storage_curr_ptr;
836  Uint32 * nextptr = currptr + len;
837  Uint32 * endptr = m_bitfield_storage_ptr + m_bitfield_storage_len;
838 
839  if (nextptr <= endptr)
840  {
841  m_bitfield_storage_curr_ptr = nextptr;
842  return currptr;
843  }
844 
845  abort();
846  return 0;
847 }
848 
849 TupleS & TupleS::operator=(const TupleS& tuple)
850 {
851  prepareRecord(*tuple.m_currentTable);
852 
853  if (allAttrData)
854  memcpy(allAttrData, tuple.allAttrData, getNoOfAttributes()*sizeof(AttributeData));
855 
856  return *this;
857 }
858 int TupleS::getNoOfAttributes() const {
859  if (m_currentTable == 0)
860  return 0;
861  return m_currentTable->getNoOfAttributes();
862 }
863 
864 TableS * TupleS::getTable() const {
865  return m_currentTable;
866 }
867 
868 AttributeDesc * TupleS::getDesc(int i) const {
869  return m_currentTable->allAttributesDesc[i];
870 }
871 
872 AttributeData * TupleS::getData(int i) const{
873  return &(allAttrData[i]);
874 }
875 
876 bool
877 TupleS::prepareRecord(TableS & tab){
878  if (allAttrData) {
879  if (getNoOfAttributes() == tab.getNoOfAttributes())
880  {
881  m_currentTable = &tab;
882  return true;
883  }
884  delete [] allAttrData;
885  m_currentTable= 0;
886  }
887 
888  allAttrData = new AttributeData[tab.getNoOfAttributes()];
889  if (allAttrData == 0)
890  return false;
891 
892  m_currentTable = &tab;
893 
894  return true;
895 }
896 
897 static
898 inline
899 Uint8*
900 pad(Uint8* src, Uint32 align, Uint32 bitPos)
901 {
902  UintPtr ptr = UintPtr(src);
903  switch(align){
904  case DictTabInfo::aBit:
905  case DictTabInfo::a32Bit:
906  case DictTabInfo::a64Bit:
907  case DictTabInfo::a128Bit:
908  return (Uint8*)(((ptr + 3) & ~(UintPtr)3) + 4 * ((bitPos + 31) >> 5));
909 charpad:
910  case DictTabInfo::an8Bit:
911  case DictTabInfo::a16Bit:
912  return src + 4 * ((bitPos + 31) >> 5);
913  default:
914 #ifdef VM_TRACE
915  abort();
916 #endif
917  goto charpad;
918  }
919 }
920 
921 const TupleS *
923 {
924  if (m_currentTable->backupVersion >= NDBD_RAW_LCP)
925  {
926  if (m_row_bitfield_len >= get_free_bitfield_storage())
927  {
933  if (free_data_callback)
934  (*free_data_callback)();
935  reset_bitfield_storage();
936  }
937  }
938 
939  Uint32 dataLength = 0;
940  // Read record length
941  if (buffer_read(&dataLength, sizeof(dataLength), 1) != 1){
942  err << "getNextTuple:Error reading length of data part" << endl;
943  res = -1;
944  return NULL;
945  } // if
946 
947  // Convert length from network byte order
948  dataLength = ntohl(dataLength);
949  const Uint32 dataLenBytes = 4 * dataLength;
950 
951  if (dataLength == 0) {
952  // Zero length for last tuple
953  // End of this data fragment
954  debug << "End of fragment" << endl;
955  res = 0;
956  return NULL;
957  } // if
958 
959  // Read tuple data
960  void *_buf_ptr;
961  if (buffer_get_ptr(&_buf_ptr, 1, dataLenBytes) != dataLenBytes) {
962  err << "getNextTuple:Read error: " << endl;
963  res = -1;
964  return NULL;
965  }
966 
967  Uint32 *buf_ptr = (Uint32*)_buf_ptr;
968  if (m_currentTable->backupVersion >= NDBD_RAW_LCP)
969  {
970  res = readTupleData_packed(buf_ptr, dataLength);
971  }
972  else
973  {
974  res = readTupleData_old(buf_ptr, dataLength);
975  }
976 
977  if (res)
978  {
979  return NULL;
980  }
981 
982  m_count ++;
983  res = 0;
984  return &m_tuple;
985 } // RestoreDataIterator::getNextTuple
986 
987 TableS *
988 RestoreDataIterator::getCurrentTable()
989 {
990  return m_currentTable;
991 }
992 
993 int
995  Uint32 dataLength)
996 {
997  Uint32 * ptr = buf_ptr;
1001  Uint32 rp = * ptr;
1002  if(unlikely(!m_hostByteOrder))
1003  rp = Twiddle32(rp);
1004 
1005  AttributeHeader ah(rp);
1006  assert(ah.getAttributeId() == AttributeHeader::READ_PACKED);
1007  Uint32 bmlen = ah.getByteSize();
1008  assert((bmlen & 3) == 0);
1009  Uint32 bmlen32 = bmlen / 4;
1010 
1014  if (!m_hostByteOrder)
1015  {
1016  for (Uint32 i = 0; i < 1 + bmlen32; i++)
1017  {
1018  ptr[i] = Twiddle32(ptr[i]);
1019  }
1020  }
1021 
1022  const NdbDictionary::Table* tab = m_currentTable->m_dictTable;
1023 
1024  // All columns should be present...
1025  assert(((tab->getNoOfColumns() + 31) >> 5) <= (int)bmlen32);
1026 
1030  const Uint32 * bmptr = ptr + 1;
1031  Uint8* src = (Uint8*)(bmptr + bmlen32);
1032  Uint32 bmpos = 0;
1033  Uint32 bitPos = 0;
1034  for (Uint32 i = 0; i < (Uint32)tab->getNoOfColumns(); i++, bmpos++)
1035  {
1036  // All columns should be present
1037  assert(BitmaskImpl::get(bmlen32, bmptr, bmpos));
1038  const NdbColumnImpl & col = NdbColumnImpl::getImpl(* tab->getColumn(i));
1039  AttributeData * attr_data = m_tuple.getData(i);
1040  const AttributeDesc * attr_desc = m_tuple.getDesc(i);
1041  if (col.getNullable())
1042  {
1043  bmpos++;
1044  if (BitmaskImpl::get(bmlen32, bmptr, bmpos))
1045  {
1046  attr_data->null = true;
1047  attr_data->void_value = NULL;
1048  continue;
1049  }
1050  }
1051 
1052  attr_data->null = false;
1053 
1057  Uint32 align = col.m_orgAttrSize;
1058  Uint32 attrSize = col.m_attrSize;
1059  Uint32 array = col.m_arraySize;
1060  Uint32 len = col.m_length;
1061  Uint32 sz = attrSize * array;
1062  Uint32 arrayType = col.m_arrayType;
1063 
1064  switch(align){
1065  case DictTabInfo::aBit:{ // Bit
1066  src = pad(src, 0, 0);
1067  Uint32* src32 = (Uint32*)src;
1068 
1069  Uint32 len32 = (len + 31) >> 5;
1070  Uint32* tmp = get_bitfield_storage(len32);
1071  attr_data->null = false;
1072  attr_data->void_value = tmp;
1073  attr_data->size = 4*len32;
1074 
1075  if (m_hostByteOrder)
1076  {
1077  BitmaskImpl::getField(1 + len32, src32, bitPos, len, tmp);
1078  }
1079  else
1080  {
1081  Uint32 ii;
1082  for (ii = 0; ii< (1 + len32); ii++)
1083  src32[ii] = Twiddle32(src32[ii]);
1084  BitmaskImpl::getField(1 + len32, (Uint32*)src, bitPos, len, tmp);
1085  for (ii = 0; ii< (1 + len32); ii++)
1086  src32[ii] = Twiddle32(src32[ii]);
1087  }
1088 
1089  src += 4 * ((bitPos + len) >> 5);
1090  bitPos = (bitPos + len) & 31;
1091  goto next;
1092  }
1093  default:
1094  src = pad(src, align, bitPos);
1095  }
1096  switch(arrayType){
1097  case NDB_ARRAYTYPE_FIXED:
1098  break;
1099  case NDB_ARRAYTYPE_SHORT_VAR:
1100  sz = 1 + src[0];
1101  break;
1102  case NDB_ARRAYTYPE_MEDIUM_VAR:
1103  sz = 2 + src[0] + 256 * src[1];
1104  break;
1105  default:
1106  abort();
1107  }
1108 
1109  attr_data->void_value = src;
1110  attr_data->size = sz;
1111 
1112  if(!Twiddle(attr_desc, attr_data))
1113  {
1114  return -1;
1115  }
1116 
1120  bitPos = 0;
1121  src += sz;
1122 next:
1123  (void)1;
1124  }
1125  return 0;
1126 }
1127 
1128 int
1129 RestoreDataIterator::readTupleData_old(Uint32 *buf_ptr,
1130  Uint32 dataLength)
1131 {
1132  Uint32 * ptr = buf_ptr;
1133  ptr += m_currentTable->m_nullBitmaskSize;
1134  Uint32 i;
1135  for(i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
1136  assert(ptr < buf_ptr + dataLength);
1137 
1138  const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId;
1139 
1140  AttributeData * attr_data = m_tuple.getData(attrId);
1141  const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
1142 
1143  const Uint32 sz = attr_desc->getSizeInWords();
1144 
1145  attr_data->null = false;
1146  attr_data->void_value = ptr;
1147  attr_data->size = 4*sz;
1148 
1149  if(!Twiddle(attr_desc, attr_data))
1150  {
1151  return -1;
1152  }
1153  ptr += sz;
1154  }
1155 
1156  for(i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
1157  assert(ptr < buf_ptr + dataLength);
1158 
1159  const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId;
1160 
1161  AttributeData * attr_data = m_tuple.getData(attrId);
1162  const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
1163 
1164  const Uint32 sz = attr_desc->getSizeInWords();
1165 
1166  attr_data->null = false;
1167  attr_data->void_value = ptr;
1168  attr_data->size = 4*sz;
1169 
1170  if(!Twiddle(attr_desc, attr_data))
1171  {
1172  return -1;
1173  }
1174 
1175  ptr += sz;
1176  }
1177 
1178  // init to NULL
1179  for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
1180  const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
1181 
1182  AttributeData * attr_data = m_tuple.getData(attrId);
1183 
1184  attr_data->null = true;
1185  attr_data->void_value = NULL;
1186  }
1187 
1188  int res;
1189  if (!isDrop6(m_currentTable->backupVersion))
1190  {
1191  if ((res = readVarData(buf_ptr, ptr, dataLength)))
1192  return res;
1193  }
1194  else
1195  {
1196  if ((res = readVarData_drop6(buf_ptr, ptr, dataLength)))
1197  return res;
1198  }
1199 
1200  return 0;
1201 }
1202 
1203 int
1204 RestoreDataIterator::readVarData(Uint32 *buf_ptr, Uint32 *ptr,
1205  Uint32 dataLength)
1206 {
1207  while (ptr + 2 < buf_ptr + dataLength)
1208  {
1209  typedef BackupFormat::DataFile::VariableData VarData;
1210  VarData * data = (VarData *)ptr;
1211  Uint32 sz = ntohl(data->Sz);
1212  Uint32 attrId = ntohl(data->Id); // column_no
1213 
1214  AttributeData * attr_data = m_tuple.getData(attrId);
1215  const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
1216 
1217  // just a reminder - remove when backwards compat implemented
1218  if (m_currentTable->backupVersion < MAKE_VERSION(5,1,3) &&
1219  attr_desc->m_column->getNullable())
1220  {
1221  const Uint32 ind = attr_desc->m_nullBitIndex;
1222  if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize,
1223  buf_ptr,ind))
1224  {
1225  attr_data->null = true;
1226  attr_data->void_value = NULL;
1227  continue;
1228  }
1229  }
1230 
1231  if (m_currentTable->backupVersion < MAKE_VERSION(5,1,3))
1232  {
1233  sz *= 4;
1234  }
1235 
1236  attr_data->null = false;
1237  attr_data->void_value = &data->Data[0];
1238  attr_data->size = sz;
1239 
1240  //convert the length of blob(v1) and text(v1)
1241  if(!Twiddle(attr_desc, attr_data))
1242  {
1243  return -1;
1244  }
1245 
1246  ptr += ((sz + 3) >> 2) + 2;
1247  }
1248 
1249  assert(ptr == buf_ptr + dataLength);
1250 
1251  return 0;
1252 }
1253 
1254 
1255 int
1256 RestoreDataIterator::readVarData_drop6(Uint32 *buf_ptr, Uint32 *ptr,
1257  Uint32 dataLength)
1258 {
1259  Uint32 i;
1260  for (i = 0; i < m_currentTable->m_variableAttribs.size(); i++)
1261  {
1262  const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
1263 
1264  AttributeData * attr_data = m_tuple.getData(attrId);
1265  const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
1266 
1267  if(attr_desc->m_column->getNullable())
1268  {
1269  const Uint32 ind = attr_desc->m_nullBitIndex;
1270  if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize,
1271  buf_ptr,ind))
1272  {
1273  attr_data->null = true;
1274  attr_data->void_value = NULL;
1275  continue;
1276  }
1277  }
1278 
1279  assert(ptr < buf_ptr + dataLength);
1280 
1281  typedef BackupFormat::DataFile::VariableData VarData;
1282  VarData * data = (VarData *)ptr;
1283  Uint32 sz = ntohl(data->Sz);
1284  Uint32 id = ntohl(data->Id);
1285  assert(id == attrId);
1286 
1287  attr_data->null = false;
1288  attr_data->void_value = &data->Data[0];
1289 
1290  if (!Twiddle(attr_desc, attr_data))
1291  {
1292  return -1;
1293  }
1294  ptr += (sz + 2);
1295  }
1296  assert(ptr == buf_ptr + dataLength);
1297  return 0;
1298 }
1299 
1300 BackupFile::BackupFile(void (* _free_data_callback)())
1301  : free_data_callback(_free_data_callback)
1302 {
1303  memset(&m_file,0,sizeof(m_file));
1304  m_path[0] = 0;
1305  m_fileName[0] = 0;
1306 
1307  m_buffer_sz = 64*1024;
1308  m_buffer = malloc(m_buffer_sz);
1309  m_buffer_ptr = m_buffer;
1310  m_buffer_data_left = 0;
1311 
1312  m_file_size = 0;
1313  m_file_pos = 0;
1314  m_is_undolog = false;
1315 }
1316 
1317 BackupFile::~BackupFile()
1318 {
1319  (void)ndbzclose(&m_file);
1320 
1321  if(m_buffer != 0)
1322  free(m_buffer);
1323 }
1324 
1325 bool
1326 BackupFile::openFile(){
1327  (void)ndbzclose(&m_file);
1328  m_file_size = 0;
1329  m_file_pos = 0;
1330 
1331  info.setLevel(254);
1332  info << "Opening file '" << m_fileName << "'\n";
1333  int r= ndbzopen(&m_file, m_fileName, O_RDONLY);
1334 
1335  if(r != 1)
1336  return false;
1337 
1338  size_t size;
1339  if (ndbz_file_size(&m_file, &size) == 0)
1340  {
1341  m_file_size = (Uint64)size;
1342  info << "File size " << m_file_size << " bytes\n";
1343  }
1344  else
1345  {
1346  info << "Progress reporting degraded output since fstat failed,"
1347  << "errno: " << errno << endl;
1348  m_file_size = 0;
1349  }
1350 
1351  return true;
1352 }
1353 
1354 Uint32 BackupFile::buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
1355 {
1356  Uint32 sz = size*nmemb;
1357  if (sz > m_buffer_data_left) {
1358 
1359  if (free_data_callback)
1360  (*free_data_callback)();
1361 
1362  reset_buffers();
1363 
1364  if (m_is_undolog)
1365  {
1366  /* move the left data to the end of buffer
1367  */
1368  size_t r = 0;
1369  int error;
1370  /* move the left data to the end of buffer
1371  * m_buffer_ptr point the end of the left data. buffer_data_start point the start of left data
1372  * m_buffer_data_left is the length of left data.
1373  */
1374  Uint64 file_left_entry_data = 0;
1375  Uint32 buffer_free_space = m_buffer_sz - m_buffer_data_left;
1376  void * buffer_end = (char *)m_buffer + m_buffer_sz;
1377  void * buffer_data_start = (char *)m_buffer_ptr - m_buffer_data_left;
1378 
1379  memmove((char *)buffer_end - m_buffer_data_left, buffer_data_start, m_buffer_data_left);
1380  buffer_data_start = (char *)buffer_end - m_buffer_data_left;
1381  /*
1382  * For undo log file we should read log entris backwards from log file.
1383  * That mean the first entries should start at sizeof(m_fileHeader).
1384  * The end of the last entries should be the end of log file(EOF-1).
1385  * If ther are entries left in log file to read.
1386  * m_file_pos should bigger than sizeof(m_fileHeader).
1387  * If the length of left log entries less than the residual length of buffer,
1388  * we just need to read all the left entries from log file into the buffer.
1389  * and all the left entries in log file should been read into buffer. Or
1390  * If the length of left entries is bigger than the residual length of buffer,
1391  * we should fill the buffer because the current buffer can't contain
1392  all the left log entries, we should read more times.
1393  *
1394  */
1395  if (m_file_pos > sizeof(m_fileHeader))
1396  {
1397  /*
1398  * We read(consume) data from the end of the buffer.
1399  * If the left data is not enough for next read in buffer,
1400  * we move the residual data to the end of buffer.
1401  * Then we will fill the start of buffer with new data from log file.
1402  * eg. If the buffer length is 10. "+" denotes useless content.
1403  * top end
1404  * Bytes in file abcdefgh0123456789
1405  * Byte in buffer 0123456789 --after first read
1406  * Consume datas... (6789) (2345)
1407  * Bytes in buffer 01++++++++ --after several consumes
1408  * Move data to end ++++++++01
1409  * Bytes in buffer abcdefgh01 --after second read
1410  */
1411  file_left_entry_data = m_file_pos - sizeof(m_fileHeader);
1412  if (file_left_entry_data <= buffer_free_space)
1413  {
1414  /* All remaining data fits in space available in buffer.
1415  * Read data into buffer before existing data.
1416  */
1417  // Move to the start of data to be read
1418  ndbzseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
1419  r = ndbzread(&m_file,
1420  (char *)buffer_data_start - file_left_entry_data,
1421  Uint32(file_left_entry_data),
1422  &error);
1423  //move back
1424  ndbzseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
1425  }
1426  else
1427  {
1428  // Fill remaing space at start of buffer with data from file.
1429  ndbzseek(&m_file, m_file_pos-buffer_free_space, SEEK_SET);
1430  r = ndbzread(&m_file, ((char *)m_buffer), buffer_free_space, &error);
1431  ndbzseek(&m_file, m_file_pos-buffer_free_space, SEEK_SET);
1432  }
1433  }
1434  m_file_pos -= r;
1435  m_buffer_data_left += (Uint32)r;
1436  //move to the end of buffer
1437  m_buffer_ptr = buffer_end;
1438  }
1439  else
1440  {
1441  memmove(m_buffer, m_buffer_ptr, m_buffer_data_left);
1442  int error;
1443  Uint32 r = ndbzread(&m_file,
1444  ((char *)m_buffer) + m_buffer_data_left,
1445  m_buffer_sz - m_buffer_data_left, &error);
1446  m_file_pos += r;
1447  m_buffer_data_left += r;
1448  m_buffer_ptr = m_buffer;
1449  }
1450 
1451  if (sz > m_buffer_data_left)
1452  sz = size * (m_buffer_data_left / size);
1453  }
1454 
1455  /*
1456  * For undolog, the m_buffer_ptr points to the end of the left data.
1457  * After we get data from the end of buffer, the data-end move forward.
1458  * So we should move m_buffer_ptr to the right place.
1459  */
1460  if(m_is_undolog)
1461  *p_buf_ptr = (char *)m_buffer_ptr - sz;
1462  else
1463  *p_buf_ptr = m_buffer_ptr;
1464 
1465  return sz/size;
1466 }
1467 Uint32 BackupFile::buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
1468 {
1469  Uint32 r = buffer_get_ptr_ahead(p_buf_ptr, size, nmemb);
1470 
1471  if(m_is_undolog)
1472  {
1473  /* we read from end of buffer to start of buffer.
1474  * m_buffer_ptr keep at the end of real data in buffer.
1475  */
1476  m_buffer_ptr = ((char*)m_buffer_ptr)-(r*size);
1477  m_buffer_data_left -= (r*size);
1478  }
1479  else
1480  {
1481  m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
1482  m_buffer_data_left -= (r*size);
1483  }
1484 
1485  return r;
1486 }
1487 
1488 Uint32 BackupFile::buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb)
1489 {
1490  void *buf_ptr;
1491  Uint32 r = buffer_get_ptr_ahead(&buf_ptr, size, nmemb);
1492  memcpy(ptr, buf_ptr, r*size);
1493 
1494  return r;
1495 }
1496 
1497 Uint32 BackupFile::buffer_read(void *ptr, Uint32 size, Uint32 nmemb)
1498 {
1499  void *buf_ptr;
1500  Uint32 r = buffer_get_ptr(&buf_ptr, size, nmemb);
1501  memcpy(ptr, buf_ptr, r*size);
1502 
1503  return r;
1504 }
1505 
1506 void
1507 BackupFile::setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path){
1508  m_nodeId = nodeId;
1509  m_expectedFileHeader.BackupId = backupId;
1510  m_expectedFileHeader.FileType = BackupFormat::CTL_FILE;
1511 
1512  char name[PATH_MAX]; const Uint32 sz = sizeof(name);
1513  BaseString::snprintf(name, sz, "BACKUP-%u.%d.ctl", backupId, nodeId);
1514  setName(path, name);
1515 }
1516 
1517 void
1518 BackupFile::setDataFile(const BackupFile & bf, Uint32 no){
1519  m_nodeId = bf.m_nodeId;
1520  m_expectedFileHeader = bf.m_fileHeader;
1521  m_expectedFileHeader.FileType = BackupFormat::DATA_FILE;
1522 
1523  char name[PATH_MAX]; const Uint32 sz = sizeof(name);
1524  BaseString::snprintf(name, sz, "BACKUP-%u-%d.%d.Data",
1525  m_expectedFileHeader.BackupId, no, m_nodeId);
1526  setName(bf.m_path, name);
1527 }
1528 
1529 void
1530 BackupFile::setLogFile(const BackupFile & bf, Uint32 no){
1531  m_nodeId = bf.m_nodeId;
1532  m_expectedFileHeader = bf.m_fileHeader;
1533  m_expectedFileHeader.FileType = BackupFormat::LOG_FILE;
1534 
1535  char name[PATH_MAX]; const Uint32 sz = sizeof(name);
1536  BaseString::snprintf(name, sz, "BACKUP-%u.%d.log",
1537  m_expectedFileHeader.BackupId, m_nodeId);
1538  setName(bf.m_path, name);
1539 }
1540 
1541 void
1542 BackupFile::setName(const char * p, const char * n){
1543  const Uint32 sz = sizeof(m_path);
1544  if(p != 0 && strlen(p) > 0){
1545  if(p[strlen(p)-1] == DIR_SEPARATOR[0]){
1546  BaseString::snprintf(m_path, sz, "%s", p);
1547  } else {
1548  BaseString::snprintf(m_path, sz, "%s%s", p, DIR_SEPARATOR);
1549  }
1550  } else {
1551  m_path[0] = 0;
1552  }
1553 
1554  BaseString::snprintf(m_fileName, sizeof(m_fileName), "%s%s", m_path, n);
1555  debug << "Filename = " << m_fileName << endl;
1556 }
1557 
1558 bool
1559 BackupFile::readHeader(){
1560  if(!openFile()){
1561  return false;
1562  }
1563 
1564  Uint32 oldsz = sizeof(BackupFormat::FileHeader_pre_backup_version);
1565  if(buffer_read(&m_fileHeader, oldsz, 1) != 1){
1566  err << "readDataFileHeader: Error reading header" << endl;
1567  return false;
1568  }
1569 
1570  // Convert from network to host byte order for platform compatibility
1571  /*
1572  Due to some optimization going on when using gcc 4.2.3 we
1573  have to read 'backup_version' into tmp variable. If
1574  'm_fileHeader.BackupVersion' is used directly in the if statement
1575  below it will have the wrong value.
1576  */
1577  Uint32 backup_version = ntohl(m_fileHeader.BackupVersion);
1578  m_fileHeader.BackupVersion = backup_version;
1579  m_fileHeader.SectionType = ntohl(m_fileHeader.SectionType);
1580  m_fileHeader.SectionLength = ntohl(m_fileHeader.SectionLength);
1581  m_fileHeader.FileType = ntohl(m_fileHeader.FileType);
1582  m_fileHeader.BackupId = ntohl(m_fileHeader.BackupId);
1583  m_fileHeader.BackupKey_0 = ntohl(m_fileHeader.BackupKey_0);
1584  m_fileHeader.BackupKey_1 = ntohl(m_fileHeader.BackupKey_1);
1585 
1586  if (backup_version >= NDBD_RAW_LCP)
1587  {
1588  if (buffer_read(&m_fileHeader.NdbVersion,
1589  sizeof(m_fileHeader) - oldsz, 1) != 1)
1590  {
1591  err << "readDataFileHeader: Error reading header" << endl;
1592  return false;
1593  }
1594 
1595  m_fileHeader.NdbVersion = ntohl(m_fileHeader.NdbVersion);
1596  m_fileHeader.MySQLVersion = ntohl(m_fileHeader.MySQLVersion);
1597  }
1598  else
1599  {
1600  m_fileHeader.NdbVersion = m_fileHeader.BackupVersion;
1601  m_fileHeader.MySQLVersion = 0;
1602  }
1603 
1604  debug << "FileHeader: " << m_fileHeader.Magic << " " <<
1605  m_fileHeader.BackupVersion << " " <<
1606  m_fileHeader.SectionType << " " <<
1607  m_fileHeader.SectionLength << " " <<
1608  m_fileHeader.FileType << " " <<
1609  m_fileHeader.BackupId << " " <<
1610  m_fileHeader.BackupKey_0 << " " <<
1611  m_fileHeader.BackupKey_1 << " " <<
1612  m_fileHeader.ByteOrder << endl;
1613 
1614  debug << "ByteOrder is " << m_fileHeader.ByteOrder << endl;
1615  debug << "magicByteOrder is " << magicByteOrder << endl;
1616 
1617 
1618  if (m_fileHeader.FileType != m_expectedFileHeader.FileType &&
1619  !(m_expectedFileHeader.FileType == BackupFormat::LOG_FILE &&
1620  m_fileHeader.FileType == BackupFormat::UNDO_FILE)){
1621  // UNDO_FILE will do in case where we expect LOG_FILE
1622  abort();
1623  }
1624 
1625  if(m_fileHeader.FileType == BackupFormat::UNDO_FILE){
1626  m_is_undolog = true;
1627  /* move pointer to end of data part.
1628  move 4 bytes from the end of file
1629  because footer contain 4 bytes 0 at the end of file.
1630  we discard the remain data stored in m_buffer.
1631  */
1632  size_t size;
1633  if (ndbz_file_size(&m_file, &size) == 0)
1634  m_file_size = (Uint64)size;
1635  ndbzseek(&m_file, 4, SEEK_END);
1636  m_file_pos = m_file_size - 4;
1637  m_buffer_data_left = 0;
1638  m_buffer_ptr = m_buffer;
1639  }
1640 
1641  // Check for BackupFormat::FileHeader::ByteOrder if swapping is needed
1642  if (m_fileHeader.ByteOrder == magicByteOrder) {
1643  m_hostByteOrder = true;
1644  } else if (m_fileHeader.ByteOrder == swappedMagicByteOrder){
1645  m_hostByteOrder = false;
1646  } else {
1647  abort();
1648  }
1649 
1650  return true;
1651 } // BackupFile::readHeader
1652 
1653 bool
1654 BackupFile::validateFooter(){
1655  return true;
1656 }
1657 
1658 bool RestoreDataIterator::readFragmentHeader(int & ret, Uint32 *fragmentId)
1659 {
1661 
1662  debug << "RestoreDataIterator::getNextFragment" << endl;
1663 
1664  while (1)
1665  {
1666  /* read first part of header */
1667  if (buffer_read(&Header, 8, 1) != 1)
1668  {
1669  ret = 0;
1670  return false;
1671  } // if
1672 
1673  /* skip if EMPTY_ENTRY */
1674  Header.SectionType = ntohl(Header.SectionType);
1675  Header.SectionLength = ntohl(Header.SectionLength);
1676  if (Header.SectionType == BackupFormat::EMPTY_ENTRY)
1677  {
1678  void *tmp;
1679  if (Header.SectionLength < 2)
1680  {
1681  err << "getFragmentFooter:Error reading fragment footer" << endl;
1682  return false;
1683  }
1684  if (Header.SectionLength > 2)
1685  buffer_get_ptr(&tmp, Header.SectionLength*4-8, 1);
1686  continue;
1687  }
1688  break;
1689  }
1690  /* read rest of header */
1691  if (buffer_read(((char*)&Header)+8, Header.SectionLength*4-8, 1) != 1)
1692  {
1693  ret = 0;
1694  return false;
1695  }
1696  Header.TableId = ntohl(Header.TableId);
1697  Header.FragmentNo = ntohl(Header.FragmentNo);
1698  Header.ChecksumType = ntohl(Header.ChecksumType);
1699 
1700  debug << "FragmentHeader: " << Header.SectionType
1701  << " " << Header.SectionLength
1702  << " " << Header.TableId
1703  << " " << Header.FragmentNo
1704  << " " << Header.ChecksumType << endl;
1705 
1706  m_currentTable = m_metaData.getTable(Header.TableId);
1707  if(m_currentTable == 0){
1708  ret = -1;
1709  return false;
1710  }
1711 
1712  if(!m_tuple.prepareRecord(*m_currentTable))
1713  {
1714  ret =-1;
1715  return false;
1716  }
1717 
1718  init_bitfield_storage(m_currentTable->m_dictTable);
1719 
1720  info.setLevel(254);
1721  info << "_____________________________________________________" << endl
1722  << "Processing data in table: " << m_currentTable->getTableName()
1723  << "(" << Header.TableId << ") fragment "
1724  << Header.FragmentNo << endl;
1725 
1726  m_count = 0;
1727  ret = 0;
1728  *fragmentId = Header.FragmentNo;
1729  return true;
1730 } // RestoreDataIterator::getNextFragment
1731 
1732 
1733 bool
1734 RestoreDataIterator::validateFragmentFooter() {
1736 
1737  if (buffer_read(&footer, sizeof(footer), 1) != 1){
1738  err << "getFragmentFooter:Error reading fragment footer" << endl;
1739  return false;
1740  }
1741 
1742  // TODO: Handle footer, nothing yet
1743  footer.SectionType = ntohl(footer.SectionType);
1744  footer.SectionLength = ntohl(footer.SectionLength);
1745  footer.TableId = ntohl(footer.TableId);
1746  footer.FragmentNo = ntohl(footer.FragmentNo);
1747  footer.NoOfRecords = ntohl(footer.NoOfRecords);
1748  footer.Checksum = ntohl(footer.Checksum);
1749 
1750  assert(m_count == footer.NoOfRecords);
1751 
1752  return true;
1753 } // RestoreDataIterator::getFragmentFooter
1754 
1755 AttributeDesc::AttributeDesc(NdbDictionary::Column *c)
1756  : m_column(c), truncation_detected(false)
1757 {
1758  size = 8*NdbColumnImpl::getImpl(* c).m_attrSize;
1759  arraySize = NdbColumnImpl::getImpl(* c).m_arraySize;
1760 }
1761 
1762 void TableS::createAttr(NdbDictionary::Column *column)
1763 {
1764  AttributeDesc * d = new AttributeDesc(column);
1765  if(d == NULL) {
1766  ndbout_c("Restore: Failed to allocate memory");
1767  abort();
1768  }
1769  d->attrId = allAttributesDesc.size();
1770  d->convertFunc = NULL;
1771  d->parameter = NULL;
1772  d->m_exclude = false;
1773  allAttributesDesc.push_back(d);
1774 
1775  if (d->m_column->getAutoIncrement())
1776  m_auto_val_attrib = d;
1777 
1778  if(d->m_column->getPrimaryKey() && backupVersion <= MAKE_VERSION(4,1,7))
1779  {
1780  m_fixedKeys.push_back(d);
1781  return;
1782  }
1783 
1784  if (d->m_column->getArrayType() == NDB_ARRAYTYPE_FIXED &&
1785  ! d->m_column->getNullable())
1786  {
1787  m_fixedAttribs.push_back(d);
1788  return;
1789  }
1790 
1791  // just a reminder - does not solve backwards compat
1792  if (backupVersion < MAKE_VERSION(5,1,3) || isDrop6(backupVersion))
1793  {
1794  d->m_nullBitIndex = m_noOfNullable;
1795  m_noOfNullable++;
1796  m_nullBitmaskSize = (m_noOfNullable + 31) / 32;
1797  }
1798  m_variableAttribs.push_back(d);
1799 } // TableS::createAttr
1800 
1801 bool
1802 TableS::get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const
1803 {
1804  /*
1805  Read current (highest) auto_increment value for
1806  a table. Currently there can only be one per table.
1807  The values are stored in sustable SYSTAB_0 as
1808  {SYSKEY,NEXTID} values where SYSKEY (32-bit) is
1809  the table_id and NEXTID (64-bit) is the next auto_increment
1810  value in the sequence (note though that sequences of
1811  values can have been fetched and that are cached in NdbAPI).
1812  SYSTAB_0 can contain other data so we need to check that
1813  the found SYSKEY value is a valid table_id (< 0x10000000).
1814  */
1815  AttributeData * attr_data = tuple.getData(0);
1816  AttributeDesc * attr_desc = tuple.getDesc(0);
1817  const AttributeS attr1 = {attr_desc, *attr_data};
1818  memcpy(syskey ,attr1.Data.u_int32_value, sizeof(Uint32));
1819  attr_data = tuple.getData(1);
1820  attr_desc = tuple.getDesc(1);
1821  const AttributeS attr2 = {attr_desc, *attr_data};
1822  memcpy(nextid, attr2.Data.u_int64_value, sizeof(Uint64));
1823  if (*syskey < 0x10000000)
1824  {
1825  return true;
1826  }
1827  return false;
1828 };
1829 
1830 Uint16 Twiddle16(Uint16 in)
1831 {
1832  Uint16 retVal = 0;
1833 
1834  retVal = ((in & 0xFF00) >> 8) |
1835  ((in & 0x00FF) << 8);
1836 
1837  return(retVal);
1838 } // Twiddle16
1839 
1840 Uint32 Twiddle32(Uint32 in)
1841 {
1842  Uint32 retVal = 0;
1843 
1844  retVal = ((in & 0x000000FF) << 24) |
1845  ((in & 0x0000FF00) << 8) |
1846  ((in & 0x00FF0000) >> 8) |
1847  ((in & 0xFF000000) >> 24);
1848 
1849  return(retVal);
1850 } // Twiddle32
1851 
1852 Uint64 Twiddle64(Uint64 in)
1853 {
1854  Uint64 retVal = 0;
1855 
1856  retVal =
1857  ((in & (Uint64)0x00000000000000FFLL) << 56) |
1858  ((in & (Uint64)0x000000000000FF00LL) << 40) |
1859  ((in & (Uint64)0x0000000000FF0000LL) << 24) |
1860  ((in & (Uint64)0x00000000FF000000LL) << 8) |
1861  ((in & (Uint64)0x000000FF00000000LL) >> 8) |
1862  ((in & (Uint64)0x0000FF0000000000LL) >> 24) |
1863  ((in & (Uint64)0x00FF000000000000LL) >> 40) |
1864  ((in & (Uint64)0xFF00000000000000LL) >> 56);
1865 
1866  return(retVal);
1867 } // Twiddle64
1868 
1869 
1870 RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md)
1871  : m_metaData(md)
1872 {
1873  debug << "RestoreLog constructor" << endl;
1874  setLogFile(md, 0);
1875 
1876  m_count = 0;
1877  m_last_gci = 0;
1878 }
1879 
1880 const LogEntry *
1881 RestoreLogIterator::getNextLogEntry(int & res) {
1882  // Read record length
1883  const Uint32 stopGCP = m_metaData.getStopGCP();
1884  Uint32 tableId;
1885  Uint32 triggerEvent;
1886  Uint32 frag_id;
1887  Uint32 *attr_data;
1888  Uint32 attr_data_len;
1889  do {
1890  Uint32 len;
1891  Uint32 *logEntryPtr;
1892  if(m_is_undolog){
1893  int read_result = 0;
1894  read_result = buffer_read(&len, sizeof(Uint32), 1);
1895  //no more log data to read
1896  if (read_result == 0 ) {
1897  res = 0;
1898  return 0;
1899  }
1900  if (read_result != 1) {
1901  res= -1;
1902  return 0;
1903  }
1904  }
1905  else{
1906  if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
1907  res= -1;
1908  return 0;
1909  }
1910  }
1911  len= ntohl(len);
1912 
1913  Uint32 data_len = sizeof(Uint32) + len*4;
1914  if (buffer_get_ptr((void **)(&logEntryPtr), 1, data_len) != data_len) {
1915  res= -2;
1916  return 0;
1917  }
1918 
1919  if(len == 0){
1920  res= 0;
1921  return 0;
1922  }
1923 
1924  if (unlikely(m_metaData.getFileHeader().NdbVersion < NDBD_FRAGID_VERSION ||
1925  isDrop6(m_metaData.getFileHeader().NdbVersion)))
1926  {
1927  /*
1928  FragId was introduced in LogEntry in version
1929  5.1.6
1930  We set FragId to 0 in older versions (these versions
1931  do not support restore of user defined partitioned
1932  tables.
1933  */
1934  typedef BackupFormat::LogFile::LogEntry_no_fragid LogE_no_fragid;
1935  LogE_no_fragid * logE_no_fragid= (LogE_no_fragid *)logEntryPtr;
1936  tableId= ntohl(logE_no_fragid->TableId);
1937  triggerEvent= ntohl(logE_no_fragid->TriggerEvent);
1938  frag_id= 0;
1939  attr_data= &logE_no_fragid->Data[0];
1940  attr_data_len= len - ((offsetof(LogE_no_fragid, Data) >> 2) - 1);
1941  }
1942  else /* normal case */
1943  {
1944  typedef BackupFormat::LogFile::LogEntry LogE;
1945  LogE * logE= (LogE *)logEntryPtr;
1946  tableId= ntohl(logE->TableId);
1947  triggerEvent= ntohl(logE->TriggerEvent);
1948  frag_id= ntohl(logE->FragId);
1949  attr_data= &logE->Data[0];
1950  attr_data_len= len - ((offsetof(LogE, Data) >> 2) - 1);
1951  }
1952 
1953  const bool hasGcp= (triggerEvent & 0x10000) != 0;
1954  triggerEvent &= 0xFFFF;
1955 
1956  if(hasGcp){
1957  // last attr_data is gci info
1958  attr_data_len--;
1959  m_last_gci = ntohl(*(attr_data + attr_data_len));
1960  }
1961  } while(m_last_gci > stopGCP + 1);
1962 
1963  m_logEntry.m_table = m_metaData.getTable(tableId);
1964  /* We should 'invert' the operation type when we restore an Undo log.
1965  * To undo an insert operation, a delete is required.
1966  * To undo a delete operation, an insert is required.
1967  * The backup have collected 'before values' for undoing 'delete+update' to make this work.
1968  * To undo insert, we only need primary key.
1969  */
1970  switch(triggerEvent){
1971  case TriggerEvent::TE_INSERT:
1972  if(m_is_undolog)
1973  m_logEntry.m_type = LogEntry::LE_DELETE;
1974  else
1975  m_logEntry.m_type = LogEntry::LE_INSERT;
1976  break;
1977  case TriggerEvent::TE_UPDATE:
1978  m_logEntry.m_type = LogEntry::LE_UPDATE;
1979  break;
1980  case TriggerEvent::TE_DELETE:
1981  if(m_is_undolog)
1982  m_logEntry.m_type = LogEntry::LE_INSERT;
1983  else
1984  m_logEntry.m_type = LogEntry::LE_DELETE;
1985  break;
1986  default:
1987  res = -1;
1988  return NULL;
1989  }
1990 
1991  const TableS * tab = m_logEntry.m_table;
1992  m_logEntry.clear();
1993 
1994  AttributeHeader * ah = (AttributeHeader *)attr_data;
1995  AttributeHeader *end = (AttributeHeader *)(attr_data + attr_data_len);
1996  AttributeS * attr;
1997  m_logEntry.m_frag_id = frag_id;
1998  while(ah < end){
1999  attr = m_logEntry.add_attr();
2000  if(attr == NULL) {
2001  ndbout_c("Restore: Failed to allocate memory");
2002  res = -1;
2003  return 0;
2004  }
2005 
2006  if(unlikely(!m_hostByteOrder))
2007  *(Uint32*)ah = Twiddle32(*(Uint32*)ah);
2008 
2009  attr->Desc = tab->getAttributeDesc(ah->getAttributeId());
2010  assert(attr->Desc != 0);
2011 
2012  const Uint32 sz = ah->getDataSize();
2013  if(sz == 0){
2014  attr->Data.null = true;
2015  attr->Data.void_value = NULL;
2016  } else {
2017  attr->Data.null = false;
2018  attr->Data.void_value = ah->getDataPtr();
2019  Twiddle(attr->Desc, &(attr->Data));
2020  }
2021 
2022 
2023  ah = ah->getNext();
2024  }
2025 
2026  m_count ++;
2027  res = 0;
2028  return &m_logEntry;
2029 }
2030 
2031 NdbOut &
2032 operator<<(NdbOut& ndbout, const AttributeS& attr){
2033  const AttributeData & data = attr.Data;
2034  const AttributeDesc & desc = *(attr.Desc);
2035 
2036  if (data.null)
2037  {
2038  ndbout << g_ndbrecord_print_format.null_string;
2039  return ndbout;
2040  }
2041 
2042  NdbRecAttr tmprec(0);
2043  tmprec.setup(desc.m_column, 0);
2044  Uint32 length = (desc.size)/8 * (desc.arraySize);
2045  tmprec.receive_data((Uint32*)data.void_value, length);
2046 
2047  ndbrecattr_print_formatted(ndbout, tmprec, g_ndbrecord_print_format);
2048 
2049  return ndbout;
2050 }
2051 
2052 // Print tuple data
2053 NdbOut&
2054 operator<<(NdbOut& ndbout, const TupleS& tuple)
2055 {
2056  for (int i = 0; i < tuple.getNoOfAttributes(); i++)
2057  {
2058  if (i > 0)
2059  ndbout << g_ndbrecord_print_format.fields_terminated_by;
2060  AttributeData * attr_data = tuple.getData(i);
2061  AttributeDesc * attr_desc = tuple.getDesc(i);
2062  const AttributeS attr = {attr_desc, *attr_data};
2063  debug << i << " " << attr_desc->m_column->getName();
2064  ndbout << attr;
2065  } // for
2066  return ndbout;
2067 }
2068 
2069 // Print tuple data
2070 NdbOut&
2071 operator<<(NdbOut& ndbout, const LogEntry& logE)
2072 {
2073  switch(logE.m_type)
2074  {
2075  case LogEntry::LE_INSERT:
2076  ndbout << "INSERT " << logE.m_table->getTableName() << " ";
2077  break;
2078  case LogEntry::LE_DELETE:
2079  ndbout << "DELETE " << logE.m_table->getTableName() << " ";
2080  break;
2081  case LogEntry::LE_UPDATE:
2082  ndbout << "UPDATE " << logE.m_table->getTableName() << " ";
2083  break;
2084  default:
2085  ndbout << "Unknown log entry type (not insert, delete or update)" ;
2086  }
2087 
2088  for (Uint32 i= 0; i < logE.size();i++)
2089  {
2090  const AttributeS * attr = logE[i];
2091  ndbout << attr->Desc->m_column->getName() << "=";
2092  ndbout << (* attr);
2093  if (i < (logE.size() - 1))
2094  ndbout << ", ";
2095  }
2096  return ndbout;
2097 }
2098 
2099 #include <NDBT.hpp>
2100 
2101 NdbOut &
2102 operator<<(NdbOut& ndbout, const TableS & table){
2103 
2104  ndbout << (* (NDBT_Table*)table.m_dictTable) << endl;
2105  return ndbout;
2106 }
2107 
2108 template class Vector<TableS*>;
2109 template class Vector<AttributeS*>;
2110 template class Vector<AttributeDesc*>;
2111 template class Vector<FragmentInfo*>;
2112 template class Vector<DictObject>;