/* Copyright (c) 2003-2005 MySQL AB, 2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include "BackupFormat.hpp" #include #include #include bool readHeader(FILE*, BackupFormat::FileHeader *); bool readFragHeader(FILE*, BackupFormat::DataFile::FragmentHeader *); bool readFragFooter(FILE*, BackupFormat::DataFile::FragmentFooter *); Int32 readRecord(FILE*, Uint32 **); NdbOut & operator<<(NdbOut&, const BackupFormat::FileHeader &); NdbOut & operator<<(NdbOut&, const BackupFormat::DataFile::FragmentHeader &); NdbOut & operator<<(NdbOut&, const BackupFormat::DataFile::FragmentFooter &); bool readTableList(FILE*, BackupFormat::CtlFile::TableList **); bool readTableDesc(FILE*, BackupFormat::CtlFile::TableDescription **); bool readGCPEntry(FILE*, BackupFormat::CtlFile::GCPEntry **); NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::TableList &); NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::TableDescription &); NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::GCPEntry &); Int32 readLogEntry(FILE*, Uint32**); static Uint32 recNo; static Uint32 logEntryNo; int main(int argc, const char * argv[]){ ndb_init(); if(argc <= 1){ printf("Usage: %s \n", argv[0]); exit(1); } FILE * f = fopen(argv[1], "rb"); if(!f){ ndbout << "No such file!" << endl; exit(1); } BackupFormat::FileHeader fileHeader; if(!readHeader(f, &fileHeader)){ ndbout << "Invalid file!" << endl; exit(1); } ndbout << fileHeader << endl; switch(fileHeader.FileType){ case BackupFormat::DATA_FILE: while(!feof(f)){ BackupFormat::DataFile::FragmentHeader fragHeader; if(!readFragHeader(f, &fragHeader)) break; ndbout << fragHeader << endl; Uint32 len, * data; while((len = readRecord(f, &data)) > 0){ #if 0 ndbout << "-> " << hex; for(Uint32 i = 0; iSectionLength - 2; for(Uint32 i = 0; i 0){ LogEntry * logEntry = (LogEntry *) data; /** * Log Entry */ Uint32 event = ntohl(logEntry->TriggerEvent); bool gcp = (event & 0x10000) != 0; event &= 0xFFFF; if(gcp) len --; ndbout << "LogEntry Table: " << (Uint32)ntohl(logEntry->TableId) << " Event: " << event << " Length: " << (len - 2); const Uint32 dataLen = len - 2; #if 0 Uint32 pos = 0; while(pos < dataLen){ AttributeHeader * ah = (AttributeHeader*)&logEntry->Data[pos]; ndbout_c(" Attribut: %d Size: %d", ah->getAttributeId(), ah->getDataSize()); pos += ah->getDataSize() + 1; } #endif if(gcp) ndbout << " GCP: " << (Uint32)ntohl(logEntry->Data[dataLen]); ndbout << endl; } break; } case BackupFormat::LCP_FILE: { BackupFormat::CtlFile::TableList * tabList; if(!readTableList(f, &tabList)){ ndbout << "Invalid file! No table list" << endl; break; } ndbout << (* tabList) << endl; const Uint32 noOfTables = tabList->SectionLength - 2; for(Uint32 i = 0; i 0){ #if 0 ndbout << "-> " << hex; for(Uint32 i = 0; iMagic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC)) != 0) RETURN_FALSE(); dst->NdbVersion = ntohl(dst->NdbVersion); if(dst->NdbVersion != NDB_VERSION) RETURN_FALSE(); if(fread(&dst->SectionType, 4, 2, f) != 2) RETURN_FALSE(); dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); if(dst->SectionType != BackupFormat::FILE_HEADER) RETURN_FALSE(); if(dst->SectionLength != ((sizeof(BackupFormat::FileHeader) - 12) >> 2)) RETURN_FALSE(); if(fread(&dst->FileType, 4, dst->SectionLength - 2, f) != (dst->SectionLength - 2)) RETURN_FALSE(); dst->FileType = ntohl(dst->FileType); dst->BackupId = ntohl(dst->BackupId); dst->BackupKey_0 = ntohl(dst->BackupKey_0); dst->BackupKey_1 = ntohl(dst->BackupKey_1); if(dst->ByteOrder != 0x12345678) endian = true; return true; } bool readFragHeader(FILE* f, BackupFormat::DataFile::FragmentHeader * dst){ if(fread(dst, 1, sizeof(* dst), f) != sizeof(* dst)) return false; dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); dst->TableId = ntohl(dst->TableId); dst->FragmentNo = ntohl(dst->FragmentNo); dst->ChecksumType = ntohl(dst->ChecksumType); if(dst->SectionLength != (sizeof(* dst) >> 2)) RETURN_FALSE(); if(dst->SectionType != BackupFormat::FRAGMENT_HEADER) RETURN_FALSE(); recNo = 0; return true; } bool readFragFooter(FILE* f, BackupFormat::DataFile::FragmentFooter * dst){ if(fread(dst, 1, sizeof(* dst), f) != sizeof(* dst)) RETURN_FALSE(); dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); dst->TableId = ntohl(dst->TableId); dst->FragmentNo = ntohl(dst->FragmentNo); dst->NoOfRecords = ntohl(dst->NoOfRecords); dst->Checksum = ntohl(dst->Checksum); if(dst->SectionLength != (sizeof(* dst) >> 2)) RETURN_FALSE(); if(dst->SectionType != BackupFormat::FRAGMENT_FOOTER) RETURN_FALSE(); return true; } static Uint32 buf[8192]; Int32 readRecord(FILE* f, Uint32 **dst){ Uint32 len; if(fread(&len, 1, 4, f) != 4) RETURN_FALSE(); len = ntohl(len); if(fread(buf, 4, len, f) != len) { return -1; } if(len > 0) recNo++; else ndbout_c("Found %d records", recNo); * dst = &buf[0]; return len; } Int32 readLogEntry(FILE* f, Uint32 **dst){ Uint32 len; if(fread(&len, 1, 4, f) != 4) RETURN_FALSE(); len = ntohl(len); if(fread(&buf[1], 4, len, f) != len) return -1; buf[0] = len; if(len > 0) logEntryNo++; * dst = &buf[0]; return len; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::FileHeader & hf){ char buf[9]; memcpy(buf, hf.Magic, sizeof(hf.Magic)); buf[8] = 0; ndbout << "-- FileHeader:" << endl; ndbout << "Magic: " << buf << endl; ndbout << "NdbVersion: " << hf.NdbVersion << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; ndbout << "FileType: " << hf.FileType << endl; ndbout << "BackupId: " << hf.BackupId << endl; ndbout << "BackupKey: [ " << hex << hf.BackupKey_0 << " "<< hf.BackupKey_1 << " ]" << endl; ndbout << "ByteOrder: " << hex << hf.ByteOrder << endl; return ndbout; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::DataFile::FragmentHeader & hf){ ndbout << "-- Fragment header:" << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; ndbout << "TableId: " << hf.TableId << endl; ndbout << "FragmentNo: " << hf.FragmentNo << endl; ndbout << "ChecksumType: " << hf.ChecksumType << endl; return ndbout; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::DataFile::FragmentFooter & hf){ ndbout << "-- Fragment footer:" << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; ndbout << "TableId: " << hf.TableId << endl; ndbout << "FragmentNo: " << hf.FragmentNo << endl; ndbout << "NoOfRecords: " << hf.NoOfRecords << endl; ndbout << "Checksum: " << hf.Checksum << endl; return ndbout; } bool readTableList(FILE* f, BackupFormat::CtlFile::TableList **ret){ BackupFormat::CtlFile::TableList * dst = (BackupFormat::CtlFile::TableList *)&buf[0]; if(fread(dst, 4, 2, f) != 2) RETURN_FALSE(); dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); if(dst->SectionType != BackupFormat::TABLE_LIST) RETURN_FALSE(); const Uint32 len = dst->SectionLength - 2; if(fread(&dst->TableIds[0], 4, len, f) != len) RETURN_FALSE(); for(Uint32 i = 0; iTableIds[i] = ntohl(dst->TableIds[i]); } * ret = dst; return true; } bool readTableDesc(FILE* f, BackupFormat::CtlFile::TableDescription **ret){ BackupFormat::CtlFile::TableDescription * dst = (BackupFormat::CtlFile::TableDescription *)&buf[0]; if(fread(dst, 4, 2, f) != 2) RETURN_FALSE(); dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); if(dst->SectionType != BackupFormat::TABLE_DESCRIPTION) RETURN_FALSE(); const Uint32 len = dst->SectionLength - 2; if(fread(&dst->DictTabInfo[0], 4, len, f) != len) RETURN_FALSE(); * ret = dst; return true; } bool readGCPEntry(FILE* f, BackupFormat::CtlFile::GCPEntry **ret){ BackupFormat::CtlFile::GCPEntry * dst = (BackupFormat::CtlFile::GCPEntry *)&buf[0]; if(fread(dst, 4, 4, f) != 4) RETURN_FALSE(); dst->SectionType = ntohl(dst->SectionType); dst->SectionLength = ntohl(dst->SectionLength); if(dst->SectionType != BackupFormat::GCP_ENTRY) RETURN_FALSE(); dst->StartGCP = ntohl(dst->StartGCP); dst->StopGCP = ntohl(dst->StopGCP); * ret = dst; return true; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::TableList & hf) { ndbout << "-- Table List:" << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; for(Uint32 i = 0; i < hf.SectionLength - 2; i++){ ndbout << hf.TableIds[i] << " "; if((i + 1) % 16 == 0) ndbout << endl; } return ndbout; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::TableDescription & hf){ ndbout << "-- Table Description:" << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; SimplePropertiesLinearReader it(&hf.DictTabInfo[0], hf.SectionLength - 2); char buf[1024]; for(it.first(); it.valid(); it.next()){ switch(it.getValueType()){ case SimpleProperties::Uint32Value: ndbout << "Key: " << it.getKey() << " value(" << it.getValueLen() << ") : " << it.getUint32() << endl; break; case SimpleProperties::StringValue: if(it.getValueLen() < sizeof(buf)){ it.getString(buf); ndbout << "Key: " << it.getKey() << " value(" << it.getValueLen() << ") : " << "\"" << buf << "\"" << endl; } else { ndbout << "Key: " << it.getKey() << " value(" << it.getValueLen() << ") : " << "\"" << "" << "\"" << endl; } break; default: ndbout << "Unknown type for key: " << it.getKey() << " type: " << it.getValueType() << endl; } } return ndbout; } NdbOut & operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::GCPEntry & hf) { ndbout << "-- GCP Entry:" << endl; ndbout << "SectionType: " << hf.SectionType << endl; ndbout << "SectionLength: " << hf.SectionLength << endl; ndbout << "Start GCP: " << hf.StartGCP << endl; ndbout << "Stop GCP: " << hf.StopGCP << endl; return ndbout; }