mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / kernel / blocks / dblqh / redoLogReader / reader.cpp
blobd065092afdd385ca73f325687f2f647ecdcc3186
1 /* Copyright (c) 2003-2005, 2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 //----------------------------------------------------------------
17 // REDOLOGFILEREADER
18 // Reads a redo log file and checks it for errors and/or prints
19 // the file in a human readable format.
21 // Usage: redoLogFileReader <file> [-noprint] [-nocheck]
22 // [-mbyte <0-15>] [-mbyteHeaders] [-pageHeaders]
23 //
24 //----------------------------------------------------------------
27 #include <ndb_global.h>
29 #include "records.hpp"
31 #define RETURN_ERROR 1
32 #define RETURN_OK 0
34 #define FROM_BEGINNING 0
36 void usage(const char * prg);
37 Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords);
38 void readArguments(int argc, const char** argv);
39 void doExit();
41 FILE * f= 0;
42 char fileName[256];
43 bool theDumpFlag = false;
44 bool thePrintFlag = true;
45 bool theCheckFlag = true;
46 bool onlyPageHeaders = false;
47 bool onlyMbyteHeaders = false;
48 bool onlyFileDesc = false;
49 bool firstLap = true;
50 Uint32 startAtMbyte = 0;
51 Uint32 startAtPage = 0;
52 Uint32 startAtPageIndex = 0;
53 Uint32 *redoLogPage;
55 NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read a redo log file", 16384) {
56 int wordIndex = 0;
57 int oldWordIndex = 0;
58 Uint32 recordType = 1234567890;
60 PageHeader *thePageHeader;
61 CompletedGCIRecord *cGCIrecord;
62 PrepareOperationRecord *poRecord;
63 NextLogRecord *nlRecord;
64 FileDescriptor *fdRecord;
65 CommitTransactionRecord *ctRecord;
66 InvalidCommitTransactionRecord *ictRecord;
67 NextMbyteRecord *nmRecord;
68 AbortTransactionRecord *atRecord;
70 readArguments(argc, argv);
72 f = fopen(fileName, "rb");
73 if(!f){
74 perror("Error: open file");
75 exit(RETURN_ERROR);
78 Uint32 tmpFileOffset = startAtMbyte * PAGESIZE * NO_PAGES_IN_MBYTE * sizeof(Uint32);
79 if (fseek(f, tmpFileOffset, FROM_BEGINNING)) {
80 perror("Error: Move in file");
81 exit(RETURN_ERROR);
84 redoLogPage = new Uint32[PAGESIZE*NO_PAGES_IN_MBYTE];
85 Uint32 words_from_previous_page = 0;
87 // Loop for every mbyte.
88 bool lastPage = false;
89 for (Uint32 j = startAtMbyte; j < NO_MBYTE_IN_FILE && !lastPage; j++) {
91 readFromFile(f, redoLogPage, PAGESIZE*NO_PAGES_IN_MBYTE);
93 words_from_previous_page = 0;
95 // Loop for every page.
96 for (int i = 0; i < NO_PAGES_IN_MBYTE; i++) {
97 wordIndex = 0;
98 thePageHeader = (PageHeader *) &redoLogPage[i*PAGESIZE];
99 // Print out mbyte number, page number and page index.
100 ndbout << j << ":" << i << ":" << wordIndex << endl
101 << " " << j*32 + i << ":" << wordIndex << " ";
102 if (thePrintFlag) ndbout << (*thePageHeader);
103 if (theCheckFlag) {
104 if(!thePageHeader->check()) {
105 ndbout << "Error in thePageHeader->check()" << endl;
106 doExit();
109 Uint32 checkSum = 37;
110 for (int ps = 1; ps < PAGESIZE; ps++)
111 checkSum = redoLogPage[i*PAGESIZE+ps] ^ checkSum;
113 if (checkSum != redoLogPage[i*PAGESIZE]){
114 ndbout << "WRONG CHECKSUM: checksum = " << redoLogPage[i*PAGESIZE]
115 << " expected = " << checkSum << endl;
116 doExit();
118 else
119 ndbout << "expected checksum: " << checkSum << endl;
123 lastPage = i != 0 && thePageHeader->lastPage();
124 Uint32 lastWord = thePageHeader->lastWord();
126 if (onlyMbyteHeaders) {
127 // Show only the first page header in every mbyte of the file.
128 break;
131 if (onlyPageHeaders) {
132 // Show only page headers. Continue with the next page in this for loop.
133 continue;
137 wordIndex = thePageHeader->getLogRecordSize() - words_from_previous_page;
138 Uint32 *redoLogPagePos = redoLogPage + i*PAGESIZE;
139 if (words_from_previous_page)
141 memmove(redoLogPagePos + wordIndex ,
142 redoLogPagePos - words_from_previous_page,
143 words_from_previous_page*4);
146 do {
147 if (words_from_previous_page)
149 // Print out mbyte number, page number and word index.
150 ndbout << j << ":" << i-1 << ":" << PAGESIZE-words_from_previous_page << endl
151 << j << ":" << i << ":" << wordIndex+words_from_previous_page << endl
152 << " " << j*32 + i-1 << ":" << PAGESIZE-words_from_previous_page << " ";
153 words_from_previous_page = 0;
155 else
157 // Print out mbyte number, page number and word index.
158 ndbout << j << ":" << i << ":" << wordIndex << endl
159 << " " << j*32 + i << ":" << wordIndex << " ";
161 redoLogPagePos = redoLogPage + i*PAGESIZE + wordIndex;
162 oldWordIndex = wordIndex;
163 recordType = *redoLogPagePos;
164 switch(recordType) {
165 case ZFD_TYPE:
166 fdRecord = (FileDescriptor *) redoLogPagePos;
167 if (thePrintFlag) ndbout << (*fdRecord);
168 if (theCheckFlag) {
169 if(!fdRecord->check()) {
170 ndbout << "Error in fdRecord->check()" << endl;
171 doExit();
174 if (onlyFileDesc) {
175 delete [] redoLogPage;
176 exit(RETURN_OK);
178 wordIndex += fdRecord->getLogRecordSize();
179 break;
181 case ZNEXT_LOG_RECORD_TYPE:
182 nlRecord = (NextLogRecord *) redoLogPagePos;
183 wordIndex += nlRecord->getLogRecordSize(wordIndex);
184 if (wordIndex <= PAGESIZE) {
185 if (thePrintFlag) ndbout << (*nlRecord);
186 if (theCheckFlag) {
187 if(!nlRecord->check()) {
188 ndbout << "Error in nlRecord->check()" << endl;
189 doExit();
193 break;
195 case ZCOMPLETED_GCI_TYPE:
196 cGCIrecord = (CompletedGCIRecord *) redoLogPagePos;
197 wordIndex += cGCIrecord->getLogRecordSize();
198 if (wordIndex <= PAGESIZE) {
199 if (thePrintFlag) ndbout << (*cGCIrecord);
200 if (theCheckFlag) {
201 if(!cGCIrecord->check()) {
202 ndbout << "Error in cGCIrecord->check()" << endl;
203 doExit();
207 break;
209 case ZPREP_OP_TYPE:
210 poRecord = (PrepareOperationRecord *) redoLogPagePos;
211 wordIndex += poRecord->getLogRecordSize(PAGESIZE-wordIndex);
212 if (wordIndex <= PAGESIZE) {
213 if (thePrintFlag) ndbout << (*poRecord);
214 if (theCheckFlag) {
215 if(!poRecord->check()) {
216 ndbout << "Error in poRecord->check()" << endl;
217 doExit();
221 break;
223 case ZCOMMIT_TYPE:
224 ctRecord = (CommitTransactionRecord *) redoLogPagePos;
225 wordIndex += ctRecord->getLogRecordSize();
226 if (wordIndex <= PAGESIZE) {
227 if (thePrintFlag) ndbout << (*ctRecord);
228 if (theCheckFlag) {
229 if(!ctRecord->check()) {
230 ndbout << "Error in ctRecord->check()" << endl;
231 doExit();
235 break;
237 case ZINVALID_COMMIT_TYPE:
238 ictRecord = (InvalidCommitTransactionRecord *) redoLogPagePos;
239 wordIndex += ictRecord->getLogRecordSize();
240 if (wordIndex <= PAGESIZE) {
241 if (thePrintFlag) ndbout << (*ictRecord);
242 if (theCheckFlag) {
243 if(!ictRecord->check()) {
244 ndbout << "Error in ictRecord->check()" << endl;
245 doExit();
249 break;
251 case ZNEXT_MBYTE_TYPE:
252 nmRecord = (NextMbyteRecord *) redoLogPagePos;
253 if (thePrintFlag) ndbout << (*nmRecord);
254 i = NO_PAGES_IN_MBYTE;
255 break;
257 case ZABORT_TYPE:
258 atRecord = (AbortTransactionRecord *) redoLogPagePos;
259 wordIndex += atRecord->getLogRecordSize();
260 if (wordIndex <= PAGESIZE) {
261 if (thePrintFlag) ndbout << (*atRecord);
262 if (theCheckFlag) {
263 if(!atRecord->check()) {
264 ndbout << "Error in atRecord->check()" << endl;
265 doExit();
269 break;
271 case ZNEW_PREP_OP_TYPE:
272 case ZFRAG_SPLIT_TYPE:
273 ndbout << endl << "Record type = " << recordType << " not implemented." << endl;
274 doExit();
276 default:
277 ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
279 // Print out remaining data in this page
280 for (int k = wordIndex; k < PAGESIZE; k++){
281 Uint32 unknown = redoLogPage[i*PAGESIZE + k];
282 ndbout_c("%-30d%-12u%-12x", k, unknown, unknown);
285 doExit();
287 } while(wordIndex < lastWord && i < NO_PAGES_IN_MBYTE);
290 if (lastPage)
292 if (theDumpFlag)
294 ndbout << " ------PAGE END: DUMPING REST OF PAGE------" << endl;
295 for (int k = wordIndex > PAGESIZE ? oldWordIndex : wordIndex;
296 k < PAGESIZE; k++)
298 Uint32 word = redoLogPage[i*PAGESIZE + k];
299 ndbout_c("%-30d%-12u%-12x", k, word, word);
302 break;
304 if (wordIndex > PAGESIZE) {
305 words_from_previous_page = PAGESIZE - oldWordIndex;
306 ndbout << " ----------- Record continues on next page -----------" << endl;
307 } else {
308 wordIndex = 0;
309 words_from_previous_page = 0;
311 ndbout << endl;
312 }//for
313 ndbout << endl;
314 if (startAtMbyte != 0) {
315 break;
317 }//for
318 fclose(f);
319 delete [] redoLogPage;
320 exit(RETURN_OK);
323 //----------------------------------------------------------------
325 //----------------------------------------------------------------
327 Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords) {
328 Uint32 noOfReadWords;
329 if ( !(noOfReadWords = fread(toPtr, sizeof(Uint32), sizeInWords, f)) ) {
330 ndbout << "Error reading file" << endl;
331 doExit();
334 return noOfReadWords;
338 //----------------------------------------------------------------
340 //----------------------------------------------------------------
343 void usage(const char * prg){
344 ndbout << endl << "Usage: " << endl << prg
345 << " <Binary log file> [-noprint] [-nocheck] [-mbyte <0-15>] "
346 << "[-mbyteheaders] [-pageheaders] [-filedescriptors] [-page <0-31>] "
347 << "[-pageindex <12-8191>]"
348 << endl << endl;
351 void readArguments(int argc, const char** argv)
353 if(argc < 2 || argc > 9){
354 usage(argv[0]);
355 doExit();
358 strcpy(fileName, argv[1]);
359 argc--;
361 int i = 2;
362 while (argc > 1)
364 if (strcmp(argv[i], "-noprint") == 0) {
365 thePrintFlag = false;
366 } else if (strcmp(argv[i], "-dump") == 0) {
367 theDumpFlag = true;
368 } else if (strcmp(argv[i], "-nocheck") == 0) {
369 theCheckFlag = false;
370 } else if (strcmp(argv[i], "-mbyteheaders") == 0) {
371 onlyMbyteHeaders = true;
372 } else if (strcmp(argv[i], "-pageheaders") == 0) {
373 onlyPageHeaders = true;
374 } else if (strcmp(argv[i], "-filedescriptors") == 0) {
375 onlyFileDesc = true;
376 } else if (strcmp(argv[i], "-mbyte") == 0) {
377 startAtMbyte = atoi(argv[i+1]);
378 if (startAtMbyte > 15) {
379 usage(argv[0]);
380 doExit();
382 argc--;
383 i++;
384 } else if (strcmp(argv[i], "-page") == 0) {
385 startAtPage = atoi(argv[i+1]);
386 if (startAtPage > 31) {
387 usage(argv[0]);
388 doExit();
390 argc--;
391 i++;
392 } else if (strcmp(argv[i], "-pageindex") == 0) {
393 startAtPageIndex = atoi(argv[i+1]);
394 if (startAtPageIndex > 8191 || startAtPageIndex < 12) {
395 usage(argv[0]);
396 doExit();
398 argc--;
399 i++;
400 } else {
401 usage(argv[0]);
402 doExit();
404 argc--;
405 i++;
410 void doExit() {
411 ndbout << "Error in redoLogReader(). Exiting!" << endl;
412 if (f) fclose(f);
413 delete [] redoLogPage;
414 exit(RETURN_ERROR);