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

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. //----------------------------------------------------------------
  14. // REDOLOGFILEREADER
  15. // Reads a redo log file and checks it for errors and/or prints
  16. // the file in a human readable format.
  17. //
  18. // Usage: redoLogFileReader <file> [-noprint] [-nocheck] 
  19. //        [-mbyte <0-15>] [-mbyteHeaders] [-pageHeaders] 
  20. //
  21. //----------------------------------------------------------------
  22. #include <ndb_global.h>
  23. #include "records.hpp"
  24. #define RETURN_ERROR 1
  25. #define RETURN_OK 0
  26. #define FROM_BEGINNING 0
  27. void usage(const char * prg);
  28. Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords);
  29. void readArguments(int argc, const char** argv);
  30. void doExit();
  31. FILE * f= 0;
  32. char fileName[256];
  33. bool theDumpFlag = false;
  34. bool thePrintFlag = true;
  35. bool theCheckFlag = true;
  36. bool onlyPageHeaders = false;
  37. bool onlyMbyteHeaders = false;
  38. bool onlyFileDesc = false;
  39. bool firstLap = true;
  40. Uint32 startAtMbyte = 0;
  41. Uint32 startAtPage = 0;
  42. Uint32 startAtPageIndex = 0;
  43. Uint32 *redoLogPage;
  44. NDB_COMMAND(redoLogFileReader,  "redoLogFileReader", "redoLogFileReader", "Read a redo log file", 16384) { 
  45.   int wordIndex = 0;
  46.   int oldWordIndex = 0;
  47.   Uint32 recordType = 1234567890;
  48.   PageHeader *thePageHeader;
  49.   CompletedGCIRecord *cGCIrecord;
  50.   PrepareOperationRecord *poRecord;
  51.   NextLogRecord *nlRecord;
  52.   FileDescriptor *fdRecord;
  53.   CommitTransactionRecord *ctRecord;
  54.   InvalidCommitTransactionRecord *ictRecord;
  55.   NextMbyteRecord *nmRecord;
  56.   AbortTransactionRecord *atRecord;
  57.   
  58.   readArguments(argc, argv);
  59.  
  60.   f = fopen(fileName, "rb");
  61.   if(!f){
  62.     perror("Error: open file");
  63.     exit(RETURN_ERROR);
  64.   }
  65.   
  66.   Uint32 tmpFileOffset = startAtMbyte * PAGESIZE * NO_PAGES_IN_MBYTE * sizeof(Uint32);
  67.   if (fseek(f, tmpFileOffset, FROM_BEGINNING)) {
  68.     perror("Error: Move in file");
  69.     exit(RETURN_ERROR);
  70.   }
  71.   redoLogPage = new Uint32[PAGESIZE*NO_PAGES_IN_MBYTE];
  72.   Uint32 words_from_previous_page = 0;
  73.   // Loop for every mbyte.
  74.   bool lastPage = false;
  75.   for (Uint32 j = startAtMbyte; j < NO_MBYTE_IN_FILE && !lastPage; j++) {
  76.     readFromFile(f, redoLogPage, PAGESIZE*NO_PAGES_IN_MBYTE);
  77.     words_from_previous_page = 0;
  78.     // Loop for every page.
  79.     for (int i = 0; i < NO_PAGES_IN_MBYTE; i++) {
  80.       wordIndex = 0;
  81.       thePageHeader = (PageHeader *) &redoLogPage[i*PAGESIZE];
  82.       // Print out mbyte number, page number and page index.
  83.       ndbout << j << ":" << i << ":" << wordIndex << endl 
  84.      << " " << j*32 + i << ":" << wordIndex << " ";
  85.       if (thePrintFlag) ndbout << (*thePageHeader);
  86.       if (theCheckFlag) {
  87. if(!thePageHeader->check()) {
  88.   ndbout << "Error in thePageHeader->check()" << endl;
  89.   doExit();
  90. }
  91. Uint32 checkSum = 37;
  92. for (int ps = 1; ps < PAGESIZE; ps++)
  93.   checkSum = redoLogPage[i*PAGESIZE+ps] ^ checkSum;
  94. if (checkSum != redoLogPage[i*PAGESIZE]){
  95.   ndbout << "WRONG CHECKSUM: checksum = " << redoLogPage[i*PAGESIZE]
  96.  << " expected = " << checkSum << endl;
  97.   doExit();
  98. }
  99. else
  100.   ndbout << "expected checksum: " << checkSum << endl;
  101.       }
  102.       lastPage = i != 0 && thePageHeader->lastPage();
  103.       Uint32 lastWord = thePageHeader->lastWord();
  104.       if (onlyMbyteHeaders) {
  105. // Show only the first page header in every mbyte of the file.
  106. break;
  107.       }
  108.       if (onlyPageHeaders) {
  109. // Show only page headers. Continue with the next page in this for loop.
  110. continue;
  111.       }
  112.       wordIndex = thePageHeader->getLogRecordSize() - words_from_previous_page;
  113.       Uint32 *redoLogPagePos = redoLogPage + i*PAGESIZE;
  114.       if (words_from_previous_page)
  115.       {
  116. memmove(redoLogPagePos + wordIndex ,
  117. redoLogPagePos - words_from_previous_page,
  118. words_from_previous_page*4);
  119.       }
  120.       do {
  121. if (words_from_previous_page)
  122. {
  123.   // Print out mbyte number, page number and word index.
  124.   ndbout << j << ":" << i-1 << ":" << PAGESIZE-words_from_previous_page << endl 
  125.  << j << ":" << i   << ":" << wordIndex+words_from_previous_page << endl 
  126.  << " " << j*32 + i-1 << ":" << PAGESIZE-words_from_previous_page << " ";
  127.   words_from_previous_page = 0;
  128. }
  129. else
  130. {
  131.   // Print out mbyte number, page number and word index.
  132.   ndbout << j << ":" << i << ":" << wordIndex << endl 
  133.  << " " << j*32 + i << ":" << wordIndex << " ";
  134. }
  135. redoLogPagePos = redoLogPage + i*PAGESIZE + wordIndex;
  136. oldWordIndex = wordIndex;
  137. recordType = *redoLogPagePos;
  138. switch(recordType) {
  139. case ZFD_TYPE:
  140.   fdRecord = (FileDescriptor *) redoLogPagePos;
  141.   if (thePrintFlag) ndbout << (*fdRecord);
  142.   if (theCheckFlag) {
  143.     if(!fdRecord->check()) {
  144.       ndbout << "Error in fdRecord->check()" << endl;
  145.       doExit();
  146.     }
  147.   }
  148.   if (onlyFileDesc) {
  149.     delete [] redoLogPage;
  150.     exit(RETURN_OK);
  151.   }
  152.   wordIndex += fdRecord->getLogRecordSize();
  153.   break;
  154.     
  155. case ZNEXT_LOG_RECORD_TYPE:
  156.   nlRecord = (NextLogRecord *) redoLogPagePos;
  157.   wordIndex += nlRecord->getLogRecordSize(wordIndex);
  158.   if (wordIndex <= PAGESIZE) {
  159.     if (thePrintFlag) ndbout << (*nlRecord);
  160.     if (theCheckFlag) {
  161.       if(!nlRecord->check()) {
  162. ndbout << "Error in nlRecord->check()" << endl;
  163. doExit();
  164.       }
  165.     }
  166.   }
  167.   break;
  168. case ZCOMPLETED_GCI_TYPE:
  169.   cGCIrecord = (CompletedGCIRecord *) redoLogPagePos;
  170.   wordIndex += cGCIrecord->getLogRecordSize();
  171.   if (wordIndex <= PAGESIZE) {
  172.     if (thePrintFlag) ndbout << (*cGCIrecord);
  173.     if (theCheckFlag) {
  174.       if(!cGCIrecord->check()) {
  175. ndbout << "Error in cGCIrecord->check()" << endl;
  176. doExit();
  177.       }
  178.     }
  179.   }
  180.   break;
  181. case ZPREP_OP_TYPE:
  182.   poRecord = (PrepareOperationRecord *) redoLogPagePos;
  183.   wordIndex += poRecord->getLogRecordSize(PAGESIZE-wordIndex);
  184.   if (wordIndex <= PAGESIZE) {
  185.     if (thePrintFlag) ndbout << (*poRecord);
  186.     if (theCheckFlag) {
  187.       if(!poRecord->check()) {
  188. ndbout << "Error in poRecord->check()" << endl;
  189. doExit();
  190.       }
  191.     }
  192.   }
  193.   break;
  194. case ZCOMMIT_TYPE:
  195.   ctRecord = (CommitTransactionRecord *) redoLogPagePos;
  196.   wordIndex += ctRecord->getLogRecordSize();
  197.   if (wordIndex <= PAGESIZE) {
  198.     if (thePrintFlag) ndbout << (*ctRecord);
  199.     if (theCheckFlag) {
  200.       if(!ctRecord->check()) {
  201. ndbout << "Error in ctRecord->check()" << endl;
  202. doExit();
  203.       }
  204.     }
  205.   }
  206.   break;
  207.       
  208. case ZINVALID_COMMIT_TYPE:
  209.   ictRecord = (InvalidCommitTransactionRecord *) redoLogPagePos;
  210.   wordIndex += ictRecord->getLogRecordSize();
  211.   if (wordIndex <= PAGESIZE) {
  212.     if (thePrintFlag) ndbout << (*ictRecord);
  213.     if (theCheckFlag) {
  214.       if(!ictRecord->check()) {
  215. ndbout << "Error in ictRecord->check()" << endl;
  216. doExit();
  217.       }
  218.     }
  219.   }
  220.   break;
  221. case ZNEXT_MBYTE_TYPE:
  222.   nmRecord = (NextMbyteRecord *) redoLogPagePos;
  223.   if (thePrintFlag) ndbout << (*nmRecord);
  224.   i = NO_PAGES_IN_MBYTE;
  225.   break;
  226. case ZABORT_TYPE:
  227.   atRecord = (AbortTransactionRecord *) redoLogPagePos;
  228.   wordIndex += atRecord->getLogRecordSize();
  229.   if (wordIndex <= PAGESIZE) {
  230.     if (thePrintFlag) ndbout << (*atRecord);
  231.     if (theCheckFlag) {
  232.       if(!atRecord->check()) {
  233. ndbout << "Error in atRecord->check()" << endl;
  234. doExit();
  235.       }
  236.     }
  237.   }
  238.   break;
  239. case ZNEW_PREP_OP_TYPE: 
  240. case ZFRAG_SPLIT_TYPE:
  241.   ndbout << endl << "Record type = " << recordType << " not implemented." << endl;
  242.   doExit();
  243. default:
  244.   ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
  245.   // Print out remaining data in this page
  246.   for (int k = wordIndex; k < PAGESIZE; k++){
  247.     Uint32 unknown = redoLogPage[i*PAGESIZE + k];
  248.     ndbout_c("%-30d%-12u%-12x", k, unknown, unknown);
  249.   }
  250.   
  251.   doExit();
  252. }
  253.       } while(wordIndex < lastWord && i < NO_PAGES_IN_MBYTE);
  254.       if (lastPage)
  255.       {
  256. if (theDumpFlag)
  257. {
  258.   ndbout << " ------PAGE END: DUMPING REST OF PAGE------" << endl;
  259.   for (int k = wordIndex > PAGESIZE ? oldWordIndex : wordIndex;
  260.        k < PAGESIZE; k++)
  261.   {
  262.     Uint32 word = redoLogPage[i*PAGESIZE + k];
  263.     ndbout_c("%-30d%-12u%-12x", k, word, word);
  264.   }
  265. }
  266. break;
  267.       }
  268.       if (wordIndex > PAGESIZE) {
  269. words_from_previous_page = PAGESIZE - oldWordIndex;
  270. ndbout << " ----------- Record continues on next page -----------" << endl;
  271.       } else {
  272. wordIndex = 0;
  273. words_from_previous_page = 0;
  274.       }
  275.       ndbout << endl;
  276.     }//for  
  277.     ndbout << endl;
  278.     if (startAtMbyte != 0) {
  279.       break;
  280.     }
  281.   }//for
  282.   fclose(f);
  283.   delete [] redoLogPage;
  284.   exit(RETURN_OK);
  285. }
  286. //----------------------------------------------------------------
  287. // 
  288. //----------------------------------------------------------------
  289. Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords) {
  290.   Uint32 noOfReadWords;
  291.   if ( !(noOfReadWords = fread(toPtr, sizeof(Uint32), sizeInWords, f)) ) {
  292.     ndbout << "Error reading file" << endl;
  293.     doExit();
  294.   } 
  295.   return noOfReadWords;
  296. }
  297. //----------------------------------------------------------------
  298. // 
  299. //----------------------------------------------------------------
  300. void usage(const char * prg){
  301.   ndbout << endl << "Usage: " << endl << prg 
  302.  << " <Binary log file> [-noprint] [-nocheck] [-mbyte <0-15>] "
  303.  << "[-mbyteheaders] [-pageheaders] [-filedescriptors] [-page <0-31>] "
  304.  << "[-pageindex <12-8191>]" 
  305.  << endl << endl;
  306.   
  307. }
  308. void readArguments(int argc, const char** argv)
  309. {
  310.   if(argc < 2 || argc > 9){
  311.     usage(argv[0]);
  312.     doExit();
  313.   }
  314.   strcpy(fileName, argv[1]);
  315.   argc--;
  316.   int i = 2;
  317.   while (argc > 1)
  318.     {
  319.       if (strcmp(argv[i], "-noprint") == 0) {
  320. thePrintFlag = false;
  321.       } else if (strcmp(argv[i], "-dump") == 0) {
  322. theDumpFlag = true;
  323.       } else if (strcmp(argv[i], "-nocheck") == 0) {
  324. theCheckFlag = false;
  325.       } else if (strcmp(argv[i], "-mbyteheaders") == 0) {
  326. onlyMbyteHeaders = true;
  327.       } else if (strcmp(argv[i], "-pageheaders") == 0) {
  328. onlyPageHeaders = true;
  329.       } else if (strcmp(argv[i], "-filedescriptors") == 0) {
  330. onlyFileDesc = true;
  331.       } else if (strcmp(argv[i], "-mbyte") == 0) {
  332. startAtMbyte = atoi(argv[i+1]);
  333. if (startAtMbyte > 15) {
  334.   usage(argv[0]);
  335.   doExit();
  336. }
  337. argc--;
  338. i++;
  339.       } else if (strcmp(argv[i], "-page") == 0) {
  340. startAtPage = atoi(argv[i+1]);
  341. if (startAtPage > 31) {
  342.   usage(argv[0]);
  343.   doExit();
  344. }
  345. argc--;
  346. i++;
  347.       } else if (strcmp(argv[i], "-pageindex") == 0) {
  348. startAtPageIndex = atoi(argv[i+1]);
  349. if (startAtPageIndex > 8191 || startAtPageIndex < 12) {
  350.   usage(argv[0]);
  351.   doExit();
  352. }
  353. argc--;
  354. i++;
  355.       } else {
  356. usage(argv[0]);
  357. doExit();
  358.       }
  359.       argc--;
  360.       i++;
  361.     }
  362.   
  363. }
  364. void doExit() {
  365.   ndbout << "Error in redoLogReader(). Exiting!" << endl;
  366.   if (f) fclose(f);
  367.   delete [] redoLogPage;
  368.   exit(RETURN_ERROR);
  369. }