summaryrefslogtreecommitdiff
path: root/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp')
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp464
1 files changed, 464 insertions, 0 deletions
diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
new file mode 100644
index 00000000000..540df7b507e
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
@@ -0,0 +1,464 @@
+/* Copyright (C) 2003 MySQL AB
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//----------------------------------------------------------------
+// REDOLOGFILEREADER
+// Reads a redo log file and checks it for errors and/or prints
+// the file in a human readable format.
+//
+// Usage: redoLogFileReader <file> [-noprint] [-nocheck]
+// [-mbyte <0-15>] [-mbyteHeaders] [-pageHeaders]
+//
+//----------------------------------------------------------------
+
+
+#include <ndb_global.h>
+
+#include "records.hpp"
+
+#define RETURN_ERROR 1
+#define RETURN_OK 0
+
+#define FROM_BEGINNING 0
+
+void usage(const char * prg);
+Uint32 readRecordOverPageBoundary (Uint32 *, Uint32 , Uint32 , Uint32);
+Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords);
+void readArguments(int argc, const char** argv);
+void doExit();
+
+FILE * f;
+char fileName[256];
+bool thePrintFlag = true;
+bool theCheckFlag = true;
+bool onlyPageHeaders = false;
+bool onlyMbyteHeaders = false;
+bool onlyFileDesc = false;
+bool firstLap = true;
+Uint32 startAtMbyte = 0;
+Uint32 startAtPage = 0;
+Uint32 startAtPageIndex = 0;
+Uint32 *redoLogPage;
+
+NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read a redo log file", 16384) {
+ Uint32 pageIndex = 0;
+ Uint32 oldPageIndex = 0;
+ Uint32 recordType = 1234567890;
+
+ PageHeader *thePageHeader;
+ CompletedGCIRecord *cGCIrecord;
+ PrepareOperationRecord *poRecord;
+ NextLogRecord *nlRecord;
+ FileDescriptor *fdRecord;
+ CommitTransactionRecord *ctRecord;
+ InvalidCommitTransactionRecord *ictRecord;
+ NextMbyteRecord *nmRecord;
+ AbortTransactionRecord *atRecord;
+
+ readArguments(argc, argv);
+
+ f = fopen(fileName, "rb");
+ if(!f){
+ perror("Error: open file");
+ exit(RETURN_ERROR);
+ }
+
+ Uint32 tmpFileOffset = startAtMbyte * PAGESIZE * NO_PAGES_IN_MBYTE * sizeof(Uint32);
+ if (fseek(f, tmpFileOffset, FROM_BEGINNING)) {
+ perror("Error: Move in file");
+ exit(RETURN_ERROR);
+ }
+
+ redoLogPage = new Uint32[PAGESIZE*NO_PAGES_IN_MBYTE];
+
+ // Loop for every mbyte.
+ for (Uint32 j = startAtMbyte; j < NO_MBYTE_IN_FILE; j++) {
+ readFromFile(f, redoLogPage, PAGESIZE*NO_PAGES_IN_MBYTE);
+
+ if (firstLap) {
+ pageIndex = startAtPageIndex;
+ firstLap = false;
+ } else
+ pageIndex = 0;
+
+ // Loop for every page.
+ for (int i = startAtPage; i < NO_PAGES_IN_MBYTE; i++) {
+
+ if (pageIndex == 0) {
+ thePageHeader = (PageHeader *) &redoLogPage[i*PAGESIZE];
+ // Print out mbyte number, page number and page index.
+ ndbout << j << ":" << i << ":" << pageIndex << endl
+ << " " << j*32 + i << ":" << pageIndex << " ";
+ if (thePrintFlag) ndbout << (*thePageHeader);
+ if (theCheckFlag) {
+ if(!thePageHeader->check()) {
+ doExit();
+ }
+
+ Uint32 checkSum = 37;
+ for (int ps = 1; ps < PAGESIZE; ps++)
+ checkSum = redoLogPage[i*PAGESIZE+ps] ^ checkSum;
+
+ if (checkSum != redoLogPage[i*PAGESIZE]){
+ ndbout << "WRONG CHECKSUM: checksum = " << redoLogPage[i*PAGESIZE]
+ << " expected = " << checkSum << endl;
+ doExit();
+ }
+ else
+ ndbout << "expected checksum: " << checkSum << endl;
+
+ }
+ pageIndex += thePageHeader->getLogRecordSize();
+ }
+
+ if (onlyMbyteHeaders) {
+ // Show only the first page header in every mbyte of the file.
+ break;
+ }
+
+ if (onlyPageHeaders) {
+ // Show only page headers. Continue with the next page in this for loop.
+ pageIndex = 0;
+ continue;
+ }
+
+ do {
+ // Print out mbyte number, page number and page index.
+ ndbout << j << ":" << i << ":" << pageIndex << endl
+ << " " << j*32 + i << ":" << pageIndex << " ";
+ recordType = redoLogPage[i*PAGESIZE + pageIndex];
+ switch(recordType) {
+ case ZFD_TYPE:
+ fdRecord = (FileDescriptor *) &redoLogPage[i*PAGESIZE + pageIndex];
+ if (thePrintFlag) ndbout << (*fdRecord);
+ if (theCheckFlag) {
+ if(!fdRecord->check()) {
+ doExit();
+ }
+ }
+ if (onlyFileDesc) {
+ delete [] redoLogPage;
+ exit(RETURN_OK);
+ }
+ pageIndex += fdRecord->getLogRecordSize();
+ break;
+
+ case ZNEXT_LOG_RECORD_TYPE:
+ nlRecord = (NextLogRecord *) (&redoLogPage[i*PAGESIZE] + pageIndex);
+ pageIndex += nlRecord->getLogRecordSize(pageIndex);
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*nlRecord);
+ if (theCheckFlag) {
+ if(!nlRecord->check()) {
+ doExit();
+ }
+ }
+ }
+ break;
+
+ case ZCOMPLETED_GCI_TYPE:
+ cGCIrecord = (CompletedGCIRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ pageIndex += cGCIrecord->getLogRecordSize();
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*cGCIrecord);
+ if (theCheckFlag) {
+ if(!cGCIrecord->check()) {
+ doExit();
+ }
+ }
+ }
+ break;
+
+ case ZPREP_OP_TYPE:
+ poRecord = (PrepareOperationRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ pageIndex += poRecord->getLogRecordSize();
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*poRecord);
+ if (theCheckFlag) {
+ if(!poRecord->check()) {
+ doExit();
+ }
+ }
+ }
+ else {
+ oldPageIndex = pageIndex - poRecord->getLogRecordSize();
+ }
+ break;
+
+ case ZCOMMIT_TYPE:
+ ctRecord = (CommitTransactionRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ pageIndex += ctRecord->getLogRecordSize();
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*ctRecord);
+ if (theCheckFlag) {
+ if(!ctRecord->check()) {
+ doExit();
+ }
+ }
+ }
+ else {
+ oldPageIndex = pageIndex - ctRecord->getLogRecordSize();
+ }
+ break;
+
+ case ZINVALID_COMMIT_TYPE:
+ ictRecord = (InvalidCommitTransactionRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ pageIndex += ictRecord->getLogRecordSize();
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*ictRecord);
+ if (theCheckFlag) {
+ if(!ictRecord->check()) {
+ doExit();
+ }
+ }
+ }
+ else {
+ oldPageIndex = pageIndex - ictRecord->getLogRecordSize();
+ }
+ break;
+
+ case ZNEXT_MBYTE_TYPE:
+ nmRecord = (NextMbyteRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ if (thePrintFlag) ndbout << (*nmRecord);
+ i = NO_PAGES_IN_MBYTE;
+ break;
+
+ case ZABORT_TYPE:
+ atRecord = (AbortTransactionRecord *) &redoLogPage[i*PAGESIZE + pageIndex];
+ pageIndex += atRecord->getLogRecordSize();
+ if (pageIndex <= PAGESIZE) {
+ if (thePrintFlag) ndbout << (*atRecord);
+ if (theCheckFlag) {
+ if(!atRecord->check()) {
+ doExit();
+ }
+ }
+ }
+ break;
+
+ case ZNEW_PREP_OP_TYPE:
+ case ZFRAG_SPLIT_TYPE:
+ ndbout << endl << "Record type = " << recordType << " not implemented." << endl;
+ doExit();
+
+ default:
+ ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
+
+ // Print out remaining data in this page
+ for (int j = pageIndex; j < PAGESIZE; j++){
+ Uint32 unknown = redoLogPage[i*PAGESIZE + j];
+
+ ndbout_c("%-30d%-12u%-12x", j, unknown, unknown);
+ }
+
+ doExit();
+ }
+ } while(pageIndex < PAGESIZE && i < NO_PAGES_IN_MBYTE);
+
+ if (pageIndex > PAGESIZE) {
+ // The last record overlapped page boundary. Must redo that record.
+ pageIndex = readRecordOverPageBoundary(&redoLogPage[i*PAGESIZE],
+ pageIndex, oldPageIndex, recordType);
+ } else {
+ pageIndex = 0;
+ }
+ ndbout << endl;
+ }//for
+ ndbout << endl;
+ if (startAtMbyte != 0) {
+ break;
+ }
+ }//for
+ fclose(f);
+ delete [] redoLogPage;
+ exit(RETURN_OK);
+}
+
+//----------------------------------------------------------------
+//
+//----------------------------------------------------------------
+
+Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords) {
+ Uint32 noOfReadWords;
+ if ( !(noOfReadWords = fread(toPtr, sizeof(Uint32), sizeInWords, f)) ) {
+ ndbout << "Error reading file" << endl;
+ doExit();
+ }
+
+ return noOfReadWords;
+}
+
+
+//----------------------------------------------------------------
+//
+//----------------------------------------------------------------
+
+Uint32 readRecordOverPageBoundary(Uint32 *pagePtr, Uint32 pageIndex, Uint32 oldPageIndex, Uint32 recordType) {
+ Uint32 pageHeader[PAGEHEADERSIZE];
+ Uint32 tmpPages[PAGESIZE*10];
+ PageHeader *thePageHeader;
+ Uint32 recordSize = 0;
+
+ PrepareOperationRecord *poRecord;
+ CommitTransactionRecord *ctRecord;
+ InvalidCommitTransactionRecord *ictRecord;
+
+ memcpy(pageHeader, pagePtr + PAGESIZE, PAGEHEADERSIZE*sizeof(Uint32));
+ memcpy(tmpPages, pagePtr + oldPageIndex, (PAGESIZE - oldPageIndex)*sizeof(Uint32));
+ memcpy(tmpPages + PAGESIZE - oldPageIndex ,
+ (pagePtr + PAGESIZE + PAGEHEADERSIZE),
+ (PAGESIZE - PAGEHEADERSIZE)*sizeof(Uint32));
+
+ switch(recordType) {
+ case ZPREP_OP_TYPE:
+ poRecord = (PrepareOperationRecord *) tmpPages;
+ recordSize = poRecord->getLogRecordSize();
+ if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) {
+ if (theCheckFlag) {
+ if(!poRecord->check()) {
+ doExit();
+ }
+ }
+ if (thePrintFlag) ndbout << (*poRecord);
+ } else {
+ ndbout << "Error: Record greater than a Page" << endl;
+ }
+ break;
+
+ case ZCOMMIT_TYPE:
+ ctRecord = (CommitTransactionRecord *) tmpPages;
+ recordSize = ctRecord->getLogRecordSize();
+ if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) {
+ if (theCheckFlag) {
+ if(!ctRecord->check()) {
+ doExit();
+ }
+ }
+ if (thePrintFlag) ndbout << (*ctRecord);
+ } else {
+ ndbout << endl << "Error: Record greater than a Page" << endl;
+ }
+ break;
+
+ case ZINVALID_COMMIT_TYPE:
+ ictRecord = (InvalidCommitTransactionRecord *) tmpPages;
+ recordSize = ictRecord->getLogRecordSize();
+ if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) {
+ if (theCheckFlag) {
+ if(!ictRecord->check()) {
+ doExit();
+ }
+ }
+ if (thePrintFlag) ndbout << (*ictRecord);
+ } else {
+ ndbout << endl << "Error: Record greater than a Page" << endl;
+ }
+ break;
+
+ case ZNEW_PREP_OP_TYPE:
+ case ZABORT_TYPE:
+ case ZFRAG_SPLIT_TYPE:
+ case ZNEXT_MBYTE_TYPE:
+ ndbout << endl << "Record type = " << recordType << " not implemented." << endl;
+ return 0;
+
+ default:
+ ndbout << endl << "Error: Unknown record type. Record type = " << recordType << endl;
+ return 0;
+ }
+
+ thePageHeader = (PageHeader *) (pagePtr + PAGESIZE);
+ if (thePrintFlag) ndbout << (*thePageHeader);
+
+ return PAGEHEADERSIZE - PAGESIZE + oldPageIndex + recordSize;
+}
+
+//----------------------------------------------------------------
+//
+//----------------------------------------------------------------
+
+
+void usage(const char * prg){
+ ndbout << endl << "Usage: " << endl << prg
+ << " <Binary log file> [-noprint] [-nocheck] [-mbyte <0-15>] "
+ << "[-mbyteheaders] [-pageheaders] [-filedescriptors] [-page <0-31>] "
+ << "[-pageindex <12-8191>]"
+ << endl << endl;
+
+}
+void readArguments(int argc, const char** argv)
+{
+ if(argc < 2 || argc > 9){
+ usage(argv[0]);
+ doExit();
+ }
+
+ strcpy(fileName, argv[1]);
+ argc--;
+
+ int i = 2;
+ while (argc > 1)
+ {
+ if (strcmp(argv[i], "-noprint") == 0) {
+ thePrintFlag = false;
+ } else if (strcmp(argv[i], "-nocheck") == 0) {
+ theCheckFlag = false;
+ } else if (strcmp(argv[i], "-mbyteheaders") == 0) {
+ onlyMbyteHeaders = true;
+ } else if (strcmp(argv[i], "-pageheaders") == 0) {
+ onlyPageHeaders = true;
+ } else if (strcmp(argv[i], "-filedescriptors") == 0) {
+ onlyFileDesc = true;
+ } else if (strcmp(argv[i], "-mbyte") == 0) {
+ startAtMbyte = atoi(argv[i+1]);
+ if (startAtMbyte > 15) {
+ usage(argv[0]);
+ doExit();
+ }
+ argc--;
+ i++;
+ } else if (strcmp(argv[i], "-page") == 0) {
+ startAtPage = atoi(argv[i+1]);
+ if (startAtPage > 31) {
+ usage(argv[0]);
+ doExit();
+ }
+ argc--;
+ i++;
+ } else if (strcmp(argv[i], "-pageindex") == 0) {
+ startAtPageIndex = atoi(argv[i+1]);
+ if (startAtPageIndex > 8191 || startAtPageIndex < 12) {
+ usage(argv[0]);
+ doExit();
+ }
+ argc--;
+ i++;
+ } else {
+ usage(argv[0]);
+ doExit();
+ }
+ argc--;
+ i++;
+ }
+
+}
+
+void doExit() {
+ ndbout << "Error in redoLogReader(). Exiting!" << endl;
+ fclose(f);
+ delete [] redoLogPage;
+ exit(RETURN_ERROR);
+}