Restore.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:23k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "Restore.hpp"
  14. #include <NdbTCP.h>
  15. #include <OutputStream.hpp>
  16. #include <Bitmask.hpp>
  17. #include <AttributeHeader.hpp>
  18. #include <trigger_definitions.h>
  19. #include <SimpleProperties.hpp>
  20. #include <signaldata/DictTabInfo.hpp>
  21. Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data
  22. Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
  23. Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
  24. bool
  25. BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Uint32 arraySize){
  26.   Uint32 i;
  27.   if(m_hostByteOrder)
  28.     return true;
  29.   
  30.   if(arraySize == 0){
  31.     arraySize = attr_desc->arraySize;
  32.   }
  33.   
  34.   switch(attr_desc->size){
  35.   case 8:
  36.     
  37.     return true;
  38.   case 16:
  39.     for(i = 0; i<arraySize; i++){
  40.       attr_data->u_int16_value[i] = Twiddle16(attr_data->u_int16_value[i]);
  41.     }
  42.     return true;
  43.   case 32:
  44.     for(i = 0; i<arraySize; i++){
  45.       attr_data->u_int32_value[i] = Twiddle32(attr_data->u_int32_value[i]);
  46.     }
  47.     return true;
  48.   case 64:
  49.     for(i = 0; i<arraySize; i++){
  50.       attr_data->u_int64_value[i] = Twiddle64(attr_data->u_int64_value[i]);
  51.     }
  52.     return true;
  53.   default:
  54.     return false;
  55.   } // switch
  56. } // Twiddle
  57. FilteredNdbOut err(* new FileOutputStream(stderr), 0, 0);
  58. FilteredNdbOut info(* new FileOutputStream(stdout), 1, 1);
  59. FilteredNdbOut debug(* new FileOutputStream(stdout), 2, 0);
  60. // To decide in what byte order data is
  61. const Uint32 magicByteOrder = 0x12345678;
  62. const Uint32 swappedMagicByteOrder = 0x78563412;
  63. RestoreMetaData::RestoreMetaData(const char* path, Uint32 nodeId, Uint32 bNo) {
  64.   
  65.   debug << "RestoreMetaData constructor" << endl;
  66.   setCtlFile(nodeId, bNo, path);
  67. }
  68. RestoreMetaData::~RestoreMetaData(){
  69.   for(Uint32 i= 0; i < allTables.size(); i++)
  70.     delete allTables[i];
  71.   allTables.clear();
  72. }
  73. TableS * 
  74. RestoreMetaData::getTable(Uint32 tableId) const {
  75.   for(Uint32 i= 0; i < allTables.size(); i++)
  76.     if(allTables[i]->getTableId() == tableId)
  77.       return allTables[i];
  78.   return NULL;
  79. }
  80. Uint32
  81. RestoreMetaData::getStopGCP() const {
  82.   return m_stopGCP;
  83. }
  84. int
  85. RestoreMetaData::loadContent() 
  86. {
  87.   Uint32 noOfTables = readMetaTableList();
  88.   if(noOfTables == 0) {
  89.     return 1;
  90.   }
  91.   for(Uint32 i = 0; i<noOfTables; i++){
  92.     if(!readMetaTableDesc()){
  93.       return 0;
  94.     }
  95.   }
  96.   if(!readGCPEntry())
  97.     return 0;
  98.   return 1;
  99. }
  100. Uint32
  101. RestoreMetaData::readMetaTableList() {
  102.   
  103.   Uint32 sectionInfo[2];
  104.   
  105.   if (buffer_read(&sectionInfo, sizeof(sectionInfo), 1) != 1){
  106.     err << "readMetaTableList read header error" << endl;
  107.     return 0;
  108.   }
  109.   sectionInfo[0] = ntohl(sectionInfo[0]);
  110.   sectionInfo[1] = ntohl(sectionInfo[1]);
  111.   const Uint32 tabCount = sectionInfo[1] - 2;
  112.   void *tmp;
  113.   if (buffer_get_ptr(&tmp, 4, tabCount) != tabCount){
  114.     err << "readMetaTableList read tabCount error" << endl;
  115.     return 0;
  116.   }
  117.   
  118.   return tabCount;
  119. }
  120. bool
  121. RestoreMetaData::readMetaTableDesc() {
  122.   
  123.   Uint32 sectionInfo[2];
  124.   
  125.   // Read section header 
  126.   if (buffer_read(&sectionInfo, sizeof(sectionInfo), 1) != 1){
  127.     err << "readMetaTableDesc read header error" << endl;
  128.     return false;
  129.   } // if
  130.   sectionInfo[0] = ntohl(sectionInfo[0]);
  131.   sectionInfo[1] = ntohl(sectionInfo[1]);
  132.   
  133.   assert(sectionInfo[0] == BackupFormat::TABLE_DESCRIPTION);
  134.   
  135.   // Read dictTabInfo buffer
  136.   const Uint32 len = (sectionInfo[1] - 2);
  137.   void *ptr;
  138.   if (buffer_get_ptr(&ptr, 4, len) != len){
  139.     err << "readMetaTableDesc read error" << endl;
  140.     return false;
  141.   } // if
  142.   
  143.   return parseTableDescriptor((Uint32*)ptr, len);      
  144. }
  145. bool
  146. RestoreMetaData::readGCPEntry() {
  147.   Uint32 data[4];
  148.   
  149.   BackupFormat::CtlFile::GCPEntry * dst = 
  150.     (BackupFormat::CtlFile::GCPEntry *)&data[0];
  151.   
  152.   if(buffer_read(dst, 4, 4) != 4){
  153.     err << "readGCPEntry read error" << endl;
  154.     return false;
  155.   }
  156.   
  157.   dst->SectionType = ntohl(dst->SectionType);
  158.   dst->SectionLength = ntohl(dst->SectionLength);
  159.   
  160.   if(dst->SectionType != BackupFormat::GCP_ENTRY){
  161.     err << "readGCPEntry invalid format" << endl;
  162.     return false;
  163.   }
  164.   
  165.   dst->StartGCP = ntohl(dst->StartGCP);
  166.   dst->StopGCP = ntohl(dst->StopGCP);
  167.   
  168.   m_startGCP = dst->StartGCP;
  169.   m_stopGCP = dst->StopGCP;
  170.   return true;
  171. }
  172. TableS::TableS(Uint32 version, NdbTableImpl* tableImpl)
  173.   : m_dictTable(tableImpl)
  174. {
  175.   m_dictTable = tableImpl;
  176.   m_noOfNullable = m_nullBitmaskSize = 0;
  177.   m_auto_val_id= ~(Uint32)0;
  178.   m_max_auto_val= 0;
  179.   backupVersion = version;
  180.   
  181.   for (int i = 0; i < tableImpl->getNoOfColumns(); i++)
  182.     createAttr(tableImpl->getColumn(i));
  183. }
  184. TableS::~TableS()
  185. {
  186.   for (Uint32 i= 0; i < allAttributesDesc.size(); i++)
  187.     delete allAttributesDesc[i];
  188. }
  189. // Parse dictTabInfo buffer and pushback to to vector storage 
  190. bool
  191. RestoreMetaData::parseTableDescriptor(const Uint32 * data, Uint32 len)
  192. {
  193.   NdbTableImpl* tableImpl = 0;
  194.   int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len, false);
  195.   if (ret != 0) {
  196.     err << "parseTableInfo " << " failed" << endl;
  197.     return false;
  198.   }
  199.   if(tableImpl == 0)
  200.     return false;
  201.   debug << "parseTableInfo " << tableImpl->getName() << " done" << endl;
  202.   TableS * table = new TableS(m_fileHeader.NdbVersion, tableImpl);
  203.   if(table == NULL) {
  204.     return false;
  205.   }
  206.   debug << "Parsed table id " << table->getTableId() << endl;
  207.   debug << "Parsed table #attr " << table->getNoOfAttributes() << endl;
  208.   debug << "Parsed table schema version not used " << endl;
  209.   debug << "Pushing table " << table->getTableName() << endl;
  210.   debug << "   with " << table->getNoOfAttributes() << " attributes" << endl;
  211.   
  212.   allTables.push_back(table);
  213.   return true;
  214. }
  215. // Constructor
  216. RestoreDataIterator::RestoreDataIterator(const RestoreMetaData & md, void (* _free_data_callback)())
  217.   : BackupFile(_free_data_callback), m_metaData(md)
  218. {
  219.   debug << "RestoreDataIterator constructor" << endl;
  220.   setDataFile(md, 0);
  221. }
  222. TupleS & TupleS::operator=(const TupleS& tuple)
  223. {
  224.   prepareRecord(*tuple.m_currentTable);
  225.   if (allAttrData)
  226.     memcpy(allAttrData, tuple.allAttrData, getNoOfAttributes()*sizeof(AttributeData));
  227.   
  228.   return *this;
  229. }
  230. int TupleS::getNoOfAttributes() const {
  231.   if (m_currentTable == 0)
  232.     return 0;
  233.   return m_currentTable->getNoOfAttributes();
  234. }
  235. TableS * TupleS::getTable() const {
  236.   return m_currentTable;
  237. }
  238. const AttributeDesc * TupleS::getDesc(int i) const {
  239.   return m_currentTable->allAttributesDesc[i];
  240. }
  241. AttributeData * TupleS::getData(int i) const{
  242.   return &(allAttrData[i]);
  243. }
  244. bool
  245. TupleS::prepareRecord(TableS & tab){
  246.   if (allAttrData) {
  247.     if (getNoOfAttributes() == tab.getNoOfAttributes())
  248.     {
  249.       m_currentTable = &tab;
  250.       return true;
  251.     }
  252.     delete [] allAttrData;
  253.     m_currentTable= 0;
  254.   }
  255.   
  256.   allAttrData = new AttributeData[tab.getNoOfAttributes()];
  257.   if (allAttrData == 0)
  258.     return false;
  259.   
  260.   m_currentTable = &tab;
  261.   return true;
  262. }
  263. const TupleS *
  264. RestoreDataIterator::getNextTuple(int  & res)
  265. {
  266.   Uint32  dataLength = 0;
  267.   // Read record length
  268.   if (buffer_read(&dataLength, sizeof(dataLength), 1) != 1){
  269.     err << "getNextTuple:Error reading length  of data part" << endl;
  270.     res = -1;
  271.     return NULL;
  272.   } // if
  273.   
  274.   // Convert length from network byte order
  275.   dataLength = ntohl(dataLength);
  276.   const Uint32 dataLenBytes = 4 * dataLength;
  277.   
  278.   if (dataLength == 0) {
  279.     // Zero length for last tuple
  280.     // End of this data fragment
  281.     debug << "End of fragment" << endl;
  282.     res = 0;
  283.     return NULL;
  284.   } // if
  285.   // Read tuple data
  286.   void *_buf_ptr;
  287.   if (buffer_get_ptr(&_buf_ptr, 1, dataLenBytes) != dataLenBytes) {
  288.     err << "getNextTuple:Read error: " << endl;
  289.     res = -1;
  290.     return NULL;
  291.   }
  292.   
  293.   Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr;
  294.   ptr += m_currentTable->m_nullBitmaskSize;
  295.   Uint32 i;
  296.   for(i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
  297.     assert(ptr < buf_ptr + dataLength);
  298.  
  299.     const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId;
  300.     AttributeData * attr_data = m_tuple.getData(attrId);
  301.     const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
  302.     const Uint32 sz = attr_desc->getSizeInWords();
  303.     attr_data->null = false;
  304.     attr_data->void_value = ptr;
  305.     if(!Twiddle(attr_desc, attr_data))
  306.       {
  307. res = -1;
  308. return NULL;
  309.       }
  310.     ptr += sz;
  311.   }
  312.   for(i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
  313.     assert(ptr < buf_ptr + dataLength);
  314.     const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId;
  315.     AttributeData * attr_data = m_tuple.getData(attrId);
  316.     const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
  317.     const Uint32 sz = attr_desc->getSizeInWords();
  318.     attr_data->null = false;
  319.     attr_data->void_value = ptr;
  320.     if(!Twiddle(attr_desc, attr_data))
  321.       {
  322. res = -1;
  323. return NULL;
  324.       }
  325.     ptr += sz;
  326.   }
  327.   for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
  328.     const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
  329.     AttributeData * attr_data = m_tuple.getData(attrId);
  330.     const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
  331.     
  332.     if(attr_desc->m_column->getNullable()){
  333.       const Uint32 ind = attr_desc->m_nullBitIndex;
  334.       if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize, 
  335.   buf_ptr,ind)){
  336. attr_data->null = true;
  337. attr_data->void_value = NULL;
  338. continue;
  339.       }
  340.     }
  341.     assert(ptr < buf_ptr + dataLength);
  342.     typedef BackupFormat::DataFile::VariableData VarData;
  343.     VarData * data = (VarData *)ptr;
  344.     Uint32 sz = ntohl(data->Sz);
  345.     Uint32 id = ntohl(data->Id);
  346.     assert(id == attrId);
  347.     
  348.     attr_data->null = false;
  349.     attr_data->void_value = &data->Data[0];
  350.     /**
  351.      * Compute array size
  352.      */
  353.     const Uint32 arraySize = (4 * sz) / (attr_desc->size / 8);
  354.     assert(arraySize >= attr_desc->arraySize);
  355.     if(!Twiddle(attr_desc, attr_data, attr_desc->arraySize))
  356.       {
  357. res = -1;
  358. return NULL;
  359.       }
  360.     ptr += (sz + 2);
  361.   }
  362.   m_count ++;  
  363.   res = 0;
  364.   return &m_tuple;
  365. } // RestoreDataIterator::getNextTuple
  366. BackupFile::BackupFile(void (* _free_data_callback)()) 
  367.   : free_data_callback(_free_data_callback)
  368. {
  369.   m_file = 0;
  370.   m_path[0] = 0;
  371.   m_fileName[0] = 0;
  372.   m_buffer_sz = 64*1024;
  373.   m_buffer = malloc(m_buffer_sz);
  374.   m_buffer_ptr = m_buffer;
  375.   m_buffer_data_left = 0;
  376. }
  377. BackupFile::~BackupFile(){
  378.   if(m_file != 0)
  379.     fclose(m_file);
  380.   if(m_buffer != 0)
  381.     free(m_buffer);
  382. }
  383. bool
  384. BackupFile::openFile(){
  385.   if(m_file != NULL){
  386.     fclose(m_file);
  387.     m_file = 0;
  388.   }
  389.   
  390.   m_file = fopen(m_fileName, "r");
  391.   return m_file != 0;
  392. }
  393. Uint32 BackupFile::buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
  394. {
  395.   Uint32 sz = size*nmemb;
  396.   if (sz > m_buffer_data_left) {
  397.     if (free_data_callback)
  398.       (*free_data_callback)();
  399.     memcpy(m_buffer, m_buffer_ptr, m_buffer_data_left);
  400.     size_t r = fread(((char *)m_buffer) + m_buffer_data_left, 1, m_buffer_sz - m_buffer_data_left, m_file);
  401.     m_buffer_data_left += r;
  402.     m_buffer_ptr = m_buffer;
  403.     if (sz > m_buffer_data_left)
  404.       sz = size * (m_buffer_data_left / size);
  405.   }
  406.   *p_buf_ptr = m_buffer_ptr;
  407.   return sz/size;
  408. }
  409. Uint32 BackupFile::buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
  410. {
  411.   Uint32 r = buffer_get_ptr_ahead(p_buf_ptr, size, nmemb);
  412.   m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
  413.   m_buffer_data_left -= (r*size);
  414.   return r;
  415. }
  416. Uint32 BackupFile::buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb)
  417. {
  418.   void *buf_ptr;
  419.   Uint32 r = buffer_get_ptr_ahead(&buf_ptr, size, nmemb);
  420.   memcpy(ptr, buf_ptr, r*size);
  421.   return r;
  422. }
  423. Uint32 BackupFile::buffer_read(void *ptr, Uint32 size, Uint32 nmemb)
  424. {
  425.   void *buf_ptr;
  426.   Uint32 r = buffer_get_ptr(&buf_ptr, size, nmemb);
  427.   memcpy(ptr, buf_ptr, r*size);
  428.   return r;
  429. }
  430. void
  431. BackupFile::setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path){
  432.   m_nodeId = nodeId;
  433.   m_expectedFileHeader.BackupId = backupId;
  434.   m_expectedFileHeader.FileType = BackupFormat::CTL_FILE;
  435.   char name[PATH_MAX]; const Uint32 sz = sizeof(name);
  436.   BaseString::snprintf(name, sz, "BACKUP-%d.%d.ctl", backupId, nodeId);  
  437.   setName(path, name);
  438. }
  439. void
  440. BackupFile::setDataFile(const BackupFile & bf, Uint32 no){
  441.   m_nodeId = bf.m_nodeId;
  442.   m_expectedFileHeader = bf.m_fileHeader;
  443.   m_expectedFileHeader.FileType = BackupFormat::DATA_FILE;
  444.   
  445.   char name[PATH_MAX]; const Uint32 sz = sizeof(name);
  446.   BaseString::snprintf(name, sz, "BACKUP-%d-%d.%d.Data", 
  447.    m_expectedFileHeader.BackupId, no, m_nodeId);
  448.   setName(bf.m_path, name);
  449. }
  450. void
  451. BackupFile::setLogFile(const BackupFile & bf, Uint32 no){
  452.   m_nodeId = bf.m_nodeId;
  453.   m_expectedFileHeader = bf.m_fileHeader;
  454.   m_expectedFileHeader.FileType = BackupFormat::LOG_FILE;
  455.   
  456.   char name[PATH_MAX]; const Uint32 sz = sizeof(name);
  457.   BaseString::snprintf(name, sz, "BACKUP-%d.%d.log", 
  458.    m_expectedFileHeader.BackupId, m_nodeId);
  459.   setName(bf.m_path, name);
  460. }
  461. void
  462. BackupFile::setName(const char * p, const char * n){
  463.   const Uint32 sz = sizeof(m_path);
  464.   if(p != 0 && strlen(p) > 0){
  465.     if(p[strlen(p)-1] == '/'){
  466.       BaseString::snprintf(m_path, sz, "%s", p);
  467.     } else {
  468.       BaseString::snprintf(m_path, sz, "%s%s", p, "/");
  469.     }
  470.   } else {
  471.     m_path[0] = 0;
  472.   }
  473.   BaseString::snprintf(m_fileName, sizeof(m_fileName), "%s%s", m_path, n);
  474.   debug << "Filename = " << m_fileName << endl;
  475. }
  476. bool
  477. BackupFile::readHeader(){
  478.   if(!openFile()){
  479.     return false;
  480.   }
  481.   
  482.   if(buffer_read(&m_fileHeader, sizeof(m_fileHeader), 1) != 1){
  483.     err << "readDataFileHeader: Error reading header" << endl;
  484.     return false;
  485.   }
  486.   
  487.   // Convert from network to host byte order for platform compatibility
  488.   m_fileHeader.NdbVersion  = ntohl(m_fileHeader.NdbVersion);
  489.   m_fileHeader.SectionType = ntohl(m_fileHeader.SectionType);
  490.   m_fileHeader.SectionLength = ntohl(m_fileHeader.SectionLength);
  491.   m_fileHeader.FileType = ntohl(m_fileHeader.FileType);
  492.   m_fileHeader.BackupId = ntohl(m_fileHeader.BackupId);
  493.   m_fileHeader.BackupKey_0 = ntohl(m_fileHeader.BackupKey_0);
  494.   m_fileHeader.BackupKey_1 = ntohl(m_fileHeader.BackupKey_1);
  495.   debug << "FileHeader: " << m_fileHeader.Magic << " " <<
  496.     m_fileHeader.NdbVersion << " " <<
  497.     m_fileHeader.SectionType << " " <<
  498.     m_fileHeader.SectionLength << " " <<
  499.     m_fileHeader.FileType << " " <<
  500.     m_fileHeader.BackupId << " " <<
  501.     m_fileHeader.BackupKey_0 << " " <<
  502.     m_fileHeader.BackupKey_1 << " " <<
  503.     m_fileHeader.ByteOrder << endl;
  504.   
  505.   debug << "ByteOrder is " << m_fileHeader.ByteOrder << endl;
  506.   debug << "magicByteOrder is " << magicByteOrder << endl;
  507.   
  508.   if (m_fileHeader.FileType != m_expectedFileHeader.FileType){
  509.     abort();
  510.   }
  511.   
  512.   // Check for BackupFormat::FileHeader::ByteOrder if swapping is needed
  513.   if (m_fileHeader.ByteOrder == magicByteOrder) {
  514.     m_hostByteOrder = true;
  515.   } else if (m_fileHeader.ByteOrder == swappedMagicByteOrder){
  516.     m_hostByteOrder = false;
  517.   } else {
  518.     abort();
  519.   }
  520.   
  521.   return true;
  522. } // BackupFile::readHeader
  523. bool
  524. BackupFile::validateFooter(){
  525.   return true;
  526. }
  527. bool RestoreDataIterator::readFragmentHeader(int & ret)
  528. {
  529.   BackupFormat::DataFile::FragmentHeader Header;
  530.   
  531.   debug << "RestoreDataIterator::getNextFragment" << endl;
  532.   
  533.   if (buffer_read(&Header, sizeof(Header), 1) != 1){
  534.     ret = 0;
  535.     return false;
  536.   } // if
  537.   
  538.   Header.SectionType  = ntohl(Header.SectionType);
  539.   Header.SectionLength  = ntohl(Header.SectionLength);
  540.   Header.TableId  = ntohl(Header.TableId);
  541.   Header.FragmentNo  = ntohl(Header.FragmentNo);
  542.   Header.ChecksumType  = ntohl(Header.ChecksumType);
  543.   
  544.   debug << "FragmentHeader: " << Header.SectionType 
  545. << " " << Header.SectionLength 
  546. << " " << Header.TableId 
  547. << " " << Header.FragmentNo 
  548. << " " << Header.ChecksumType << endl;
  549.   
  550.   m_currentTable = m_metaData.getTable(Header.TableId);
  551.   if(m_currentTable == 0){
  552.     ret = -1;
  553.     return false;
  554.   }
  555.   
  556.   if(!m_tuple.prepareRecord(*m_currentTable))
  557.   {
  558.     ret =-1;
  559.     return false;
  560.   }
  561.   info << "_____________________________________________________" << endl
  562.        << "Restoring data in table: " << m_currentTable->getTableName() 
  563.        << "(" << Header.TableId << ") fragment " 
  564.        << Header.FragmentNo << endl;
  565.   
  566.   m_count = 0;
  567.   ret = 0;
  568.   return true;
  569. } // RestoreDataIterator::getNextFragment
  570. bool
  571. RestoreDataIterator::validateFragmentFooter() {
  572.   BackupFormat::DataFile::FragmentFooter footer;
  573.   
  574.   if (buffer_read(&footer, sizeof(footer), 1) != 1){
  575.     err << "getFragmentFooter:Error reading fragment footer" << endl;
  576.     return false;
  577.   } 
  578.   
  579.   // TODO: Handle footer, nothing yet
  580.   footer.SectionType  = ntohl(footer.SectionType);
  581.   footer.SectionLength  = ntohl(footer.SectionLength);
  582.   footer.TableId  = ntohl(footer.TableId);
  583.   footer.FragmentNo  = ntohl(footer.FragmentNo);
  584.   footer.NoOfRecords  = ntohl(footer.NoOfRecords);
  585.   footer.Checksum  = ntohl(footer.Checksum);
  586.   assert(m_count == footer.NoOfRecords);
  587.   
  588.   return true;
  589. } // RestoreDataIterator::getFragmentFooter
  590. AttributeDesc::AttributeDesc(NdbDictionary::Column *c)
  591.   : m_column(c)
  592. {
  593.   size = 8*NdbColumnImpl::getImpl(* c).m_attrSize;
  594.   arraySize = NdbColumnImpl::getImpl(* c).m_arraySize;
  595. }
  596. void TableS::createAttr(NdbDictionary::Column *column)
  597. {
  598.   AttributeDesc * d = new AttributeDesc(column);
  599.   if(d == NULL) {
  600.     ndbout_c("Restore: Failed to allocate memory");
  601.     abort();
  602.   }
  603.   d->attrId = allAttributesDesc.size();
  604.   allAttributesDesc.push_back(d);
  605.   if (d->m_column->getAutoIncrement())
  606.     m_auto_val_id= d->attrId;
  607.   if(d->m_column->getPrimaryKey() && backupVersion <= MAKE_VERSION(4,1,7))
  608.   {
  609.     m_fixedKeys.push_back(d);
  610.     return;
  611.   }
  612.   
  613.   if(!d->m_column->getNullable())
  614.   {
  615.     m_fixedAttribs.push_back(d);
  616.     return;
  617.   }
  618.   /* Nullable attr*/
  619.   d->m_nullBitIndex = m_noOfNullable; 
  620.   m_noOfNullable++;
  621.   m_nullBitmaskSize = (m_noOfNullable + 31) / 32;
  622.   m_variableAttribs.push_back(d);
  623. } // TableS::createAttr
  624. Uint16 Twiddle16(Uint16 in)
  625. {
  626.   Uint16 retVal = 0;
  627.   retVal = ((in & 0xFF00) >> 8) |
  628.     ((in & 0x00FF) << 8);
  629.   return(retVal);
  630. } // Twiddle16
  631. Uint32 Twiddle32(Uint32 in)
  632. {
  633.   Uint32 retVal = 0;
  634.   retVal = ((in & 0x000000FF) << 24) | 
  635.     ((in & 0x0000FF00) << 8)  |
  636.     ((in & 0x00FF0000) >> 8)  |
  637.     ((in & 0xFF000000) >> 24);
  638.   
  639.   return(retVal);
  640. } // Twiddle32
  641. Uint64 Twiddle64(Uint64 in)
  642. {
  643.   Uint64 retVal = 0;
  644.   retVal = 
  645.     ((in & (Uint64)0x00000000000000FFLL) << 56) | 
  646.     ((in & (Uint64)0x000000000000FF00LL) << 40) | 
  647.     ((in & (Uint64)0x0000000000FF0000LL) << 24) | 
  648.     ((in & (Uint64)0x00000000FF000000LL) << 8) | 
  649.     ((in & (Uint64)0x000000FF00000000LL) >> 8) | 
  650.     ((in & (Uint64)0x0000FF0000000000LL) >> 24) | 
  651.     ((in & (Uint64)0x00FF000000000000LL) >> 40) | 
  652.     ((in & (Uint64)0xFF00000000000000LL) >> 56);
  653.   return(retVal);
  654. } // Twiddle64
  655. RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md)
  656.   : m_metaData(md) 
  657. {
  658.   debug << "RestoreLog constructor" << endl;
  659.   setLogFile(md, 0);
  660.   m_count = 0;
  661.   m_last_gci = 0;
  662. }
  663. const LogEntry *
  664. RestoreLogIterator::getNextLogEntry(int & res) {
  665.   // Read record length
  666.   typedef BackupFormat::LogFile::LogEntry LogE;
  667.   LogE * logE= 0;
  668.   Uint32 len= ~0;
  669.   const Uint32 stopGCP = m_metaData.getStopGCP();
  670.   do {
  671.     if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
  672.       res= -1;
  673.       return 0;
  674.     }
  675.     len= ntohl(len);
  676.     Uint32 data_len = sizeof(Uint32) + len*4;
  677.     if (buffer_get_ptr((void **)(&logE), 1, data_len) != data_len) {
  678.       res= -2;
  679.       return 0;
  680.     }
  681.     
  682.     if(len == 0){
  683.       res= 0;
  684.       return 0;
  685.     }
  686.     logE->TableId= ntohl(logE->TableId);
  687.     logE->TriggerEvent= ntohl(logE->TriggerEvent);
  688.     
  689.     const bool hasGcp= (logE->TriggerEvent & 0x10000) != 0;
  690.     logE->TriggerEvent &= 0xFFFF;
  691.     
  692.     if(hasGcp){
  693.       len--;
  694.       m_last_gci = ntohl(logE->Data[len-2]);
  695.     }
  696.   } while(m_last_gci > stopGCP + 1);
  697.   
  698.   m_logEntry.m_table = m_metaData.getTable(logE->TableId);
  699.   switch(logE->TriggerEvent){
  700.   case TriggerEvent::TE_INSERT:
  701.     m_logEntry.m_type = LogEntry::LE_INSERT;
  702.     break;
  703.   case TriggerEvent::TE_UPDATE:
  704.     m_logEntry.m_type = LogEntry::LE_UPDATE;
  705.     break;
  706.   case TriggerEvent::TE_DELETE:
  707.     m_logEntry.m_type = LogEntry::LE_DELETE;
  708.     break;
  709.   default:
  710.     res = -1;
  711.     return NULL;
  712.   }
  713.   const TableS * tab = m_logEntry.m_table;
  714.   m_logEntry.clear();
  715.   AttributeHeader * ah = (AttributeHeader *)&logE->Data[0];
  716.   AttributeHeader *end = (AttributeHeader *)&logE->Data[len - 2];
  717.   AttributeS *  attr;
  718.   while(ah < end){
  719.     attr= m_logEntry.add_attr();
  720.     if(attr == NULL) {
  721.       ndbout_c("Restore: Failed to allocate memory");
  722.       res = -1;
  723.       return 0;
  724.     }
  725.     attr->Desc = (* tab)[ah->getAttributeId()];
  726.     assert(attr->Desc != 0);
  727.     const Uint32 sz = ah->getDataSize();
  728.     if(sz == 0){
  729.       attr->Data.null = true;
  730.       attr->Data.void_value = NULL;
  731.     } else {
  732.       attr->Data.null = false;
  733.       attr->Data.void_value = ah->getDataPtr();
  734.     }
  735.     
  736.     Twiddle(attr->Desc, &(attr->Data));
  737.     
  738.     ah = ah->getNext();
  739.   }
  740.   m_count ++;
  741.   res = 0;
  742.   return &m_logEntry;
  743. }
  744. NdbOut &
  745. operator<<(NdbOut& ndbout, const AttributeS& attr){
  746.   const AttributeData & data = attr.Data;
  747.   const AttributeDesc & desc = *(attr.Desc);
  748.   if (data.null)
  749.   {
  750.     ndbout << "<NULL>";
  751.     return ndbout;
  752.   }
  753.   
  754.   NdbRecAttr tmprec(0);
  755.   tmprec.setup(desc.m_column, (char *)data.void_value);
  756.   ndbout << tmprec;
  757.   return ndbout;
  758. }
  759. // Print tuple data
  760. NdbOut& 
  761. operator<<(NdbOut& ndbout, const TupleS& tuple)
  762. {
  763.   ndbout << tuple.getTable()->getTableName() << "; ";
  764.   for (int i = 0; i < tuple.getNoOfAttributes(); i++) 
  765.   {
  766.     AttributeData * attr_data = tuple.getData(i);
  767.     const AttributeDesc * attr_desc = tuple.getDesc(i);
  768.     const AttributeS attr = {attr_desc, *attr_data};
  769.     debug << i << " " << attr_desc->m_column->getName();
  770.     ndbout << attr;
  771.     
  772.     if (i != (tuple.getNoOfAttributes() - 1))
  773.       ndbout << delimiter << " ";
  774.   } // for
  775.   return ndbout;
  776. }
  777. // Print tuple data
  778. NdbOut& 
  779. operator<<(NdbOut& ndbout, const LogEntry& logE)
  780. {
  781.   switch(logE.m_type)
  782.   {
  783.   case LogEntry::LE_INSERT:
  784.     ndbout << "INSERT " << logE.m_table->getTableName() << " ";
  785.     break;
  786.   case LogEntry::LE_DELETE:
  787.     ndbout << "DELETE " << logE.m_table->getTableName() << " ";
  788.     break;
  789.   case LogEntry::LE_UPDATE:
  790.     ndbout << "UPDATE " << logE.m_table->getTableName() << " ";
  791.     break;
  792.   default:
  793.     ndbout << "Unknown log entry type (not insert, delete or update)" ;
  794.   }
  795.   
  796.   for (Uint32 i= 0; i < logE.size();i++) 
  797.   {
  798.     const AttributeS * attr = logE[i];
  799.     ndbout << attr->Desc->m_column->getName() << "=";
  800.     ndbout << (* attr);
  801.     if (i < (logE.size() - 1))
  802.       ndbout << ", ";
  803.   }
  804.   return ndbout;
  805. }
  806. NdbOut & 
  807. operator<<(NdbOut& ndbout, const TableS & table){
  808.   ndbout << endl << "Table: " << table.getTableName() << endl;
  809.   for (int j = 0; j < table.getNoOfAttributes(); j++) 
  810.   {
  811.     const AttributeDesc * desc = table[j];
  812.     ndbout << desc->m_column->getName() << ": "
  813.    << (Uint32) desc->m_column->getType();
  814.     ndbout << " key: "  << (Uint32) desc->m_column->getPrimaryKey();
  815.     ndbout << " array: " << desc->arraySize;
  816.     ndbout << " size: " << desc->size << endl;
  817.   } // for
  818.   return ndbout;
  819. }
  820. template class Vector<TableS*>;
  821. template class Vector<AttributeS*>;
  822. template class Vector<AttributeDesc*>;