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

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 <ndb_global.h>
  14. #include "Error.hpp"
  15. #include "ErrorReporter.hpp"
  16. #include "ErrorMessages.hpp"
  17. #include <FastScheduler.hpp>
  18. #include <DebuggerNames.hpp>
  19. #include <NdbHost.h>
  20. #include <NdbConfig.h>
  21. #include <Configuration.hpp>
  22. #include <NdbAutoPtr.hpp>
  23. #define MESSAGE_LENGTH 400
  24. const char* errorType[] = { 
  25.   "warning", 
  26.   "error", 
  27.   "fatal", 
  28.   "assert"
  29. };
  30. static int WriteMessage(ErrorCategory thrdType, int thrdMessageID,
  31. const char* thrdProblemData, 
  32. const char* thrdObjRef,
  33. Uint32 thrdTheEmulatedJamIndex,
  34. Uint8 thrdTheEmulatedJam[]);
  35. static void dumpJam(FILE* jamStream, 
  36.     Uint32 thrdTheEmulatedJamIndex, 
  37.     Uint8 thrdTheEmulatedJam[]);
  38. const char*
  39. ErrorReporter::formatTimeStampString(){
  40.   TimeModule DateTime;          /* To create "theDateTimeString" */
  41.   
  42.   static char theDateTimeString[39]; 
  43.   /* Used to store the generated timestamp */
  44.   /* ex: "Wednesday 18 September 2000 - 18:54:37" */
  45.   DateTime.setTimeStamp();
  46.   
  47.   BaseString::snprintf(theDateTimeString, 39, "%s %d %s %d - %s:%s:%s", 
  48.    DateTime.getDayName(), DateTime.getDayOfMonth(),
  49.    DateTime.getMonthName(), DateTime.getYear(), DateTime.getHour(),
  50.    DateTime.getMinute(), DateTime.getSecond());
  51.   
  52.   return (const char *)&theDateTimeString;
  53. }
  54. int
  55. ErrorReporter::get_trace_no(){
  56.   
  57.   FILE *stream;
  58.   unsigned int traceFileNo;
  59.   
  60.   char *file_name= NdbConfig_NextTraceFileName(globalData.ownId);
  61.   NdbAutoPtr<char> tmp_aptr(file_name);
  62.   /* 
  63.    * Read last number from tracefile
  64.    */  
  65.   stream = fopen(file_name, "r+");
  66.   if (stream == NULL){
  67.     traceFileNo = 1;
  68.   } else {
  69.     char buf[255];
  70.     fgets(buf, 255, stream);
  71.     const int scan = sscanf(buf, "%u", &traceFileNo);
  72.     if(scan != 1){
  73.       traceFileNo = 1;
  74.     }
  75.     fclose(stream);
  76.     traceFileNo++;
  77.   }
  78.   /**
  79.    * Wrap tracefile no 
  80.    */
  81.   Uint32 tmp = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
  82.   if (traceFileNo > tmp ) {
  83.     traceFileNo = 1;
  84.   }
  85.   /**
  86.    *  Save new number to the file
  87.    */
  88.   stream = fopen(file_name, "w");
  89.   if(stream != NULL){
  90.     fprintf(stream, "%u", traceFileNo);
  91.     fclose(stream);
  92.   }
  93.   return traceFileNo;
  94. }
  95. void
  96. ErrorReporter::formatMessage(ErrorCategory type, 
  97.      int faultID,
  98.      const char* problemData, 
  99.      const char* objRef,
  100.      const char* theNameOfTheTraceFile,
  101.      char* messptr){
  102.   int processId;
  103.   
  104.   processId = NdbHost_GetProcessId();
  105.   
  106.   BaseString::snprintf(messptr, MESSAGE_LENGTH,
  107.    "Date/Time: %snType of error: %sn"
  108.    "Message: %snFault ID: %dnProblem data: %s"
  109.    "nObject of reference: %snProgramName: %sn"
  110.    "ProcessID: %dnTraceFile: %sn%sn***EOM***n", 
  111.    formatTimeStampString() , 
  112.    errorType[type], 
  113.    lookupErrorMessage(faultID),
  114.    faultID, 
  115.    (problemData == NULL) ? "" : problemData, 
  116.    objRef, 
  117.    my_progname, 
  118.    processId, 
  119.    theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>",
  120.        NDB_VERSION_STRING);
  121.   // Add trailing blanks to get a fixed lenght of the message
  122.   while (strlen(messptr) <= MESSAGE_LENGTH-3){
  123.     strcat(messptr, " ");
  124.   }
  125.   
  126.   strcat(messptr, "n");
  127.   
  128.   return;
  129. }
  130. NdbShutdownType ErrorReporter::s_errorHandlerShutdownType = NST_ErrorHandler;
  131. void
  132. ErrorReporter::setErrorHandlerShutdownType(NdbShutdownType nst)
  133. {
  134.   s_errorHandlerShutdownType = nst;
  135. }
  136. void
  137. ErrorReporter::handleAssert(const char* message, const char* file, int line)
  138. {
  139.   char refMessage[100];
  140. #ifdef NO_EMULATED_JAM
  141.   BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d",
  142.    file, line);
  143. #else
  144.   const Uint32 blockNumber = theEmulatedJamBlockNumber;
  145.   const char *blockName = getBlockName(blockNumber);
  146.   BaseString::snprintf(refMessage, 100, "%s line: %d (block: %s)",
  147.    file, line, blockName);
  148. #endif
  149.   WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage,
  150.        theEmulatedJamIndex, theEmulatedJam);
  151.   NdbShutdown(s_errorHandlerShutdownType);
  152. }
  153. void
  154. ErrorReporter::handleThreadAssert(const char* message,
  155.                                   const char* file,
  156.                                   int line)
  157. {
  158.   char refMessage[100];
  159.   BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d - %s",
  160.    file, line, message);
  161.   
  162.   NdbShutdown(s_errorHandlerShutdownType);
  163. }//ErrorReporter::handleThreadAssert()
  164. void
  165. ErrorReporter::handleError(ErrorCategory type, int messageID,
  166.    const char* problemData, 
  167.    const char* objRef,
  168.    NdbShutdownType nst)
  169. {
  170.   type = ecError; 
  171.   // The value for type is not always set correctly in the calling function.
  172.   // So, to correct this, we set it set it to the value corresponding to
  173.   // the function that is called.
  174.   WriteMessage(type, messageID, problemData,
  175.        objRef, theEmulatedJamIndex, theEmulatedJam);
  176.   if(messageID == ERR_ERROR_INSERT){
  177.     NdbShutdown(NST_ErrorInsert);
  178.   } else {
  179.     if (nst == NST_ErrorHandler)
  180.       nst = s_errorHandlerShutdownType;
  181.     NdbShutdown(nst);
  182.   }
  183. }
  184. int 
  185. WriteMessage(ErrorCategory thrdType, int thrdMessageID,
  186.      const char* thrdProblemData, const char* thrdObjRef,
  187.      Uint32 thrdTheEmulatedJamIndex,
  188.      Uint8 thrdTheEmulatedJam[]){
  189.   FILE *stream;
  190.   unsigned offset;
  191.   unsigned long maxOffset;  // Maximum size of file.
  192.   char theMessage[MESSAGE_LENGTH];
  193.   /**
  194.    * Format trace file name
  195.    */
  196.   char *theTraceFileName= 0;
  197.   if (globalData.ownId > 0)
  198.     theTraceFileName= NdbConfig_TraceFileName(globalData.ownId,
  199.       ErrorReporter::get_trace_no());
  200.   NdbAutoPtr<char> tmp_aptr1(theTraceFileName);
  201.   
  202.   // The first 69 bytes is info about the current offset
  203.   Uint32 noMsg = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
  204.   maxOffset = (69 + (noMsg * MESSAGE_LENGTH));
  205.   
  206.   char *theErrorFileName= (char *)NdbConfig_ErrorFileName(globalData.ownId);
  207.   NdbAutoPtr<char> tmp_aptr2(theErrorFileName);
  208.   stream = fopen(theErrorFileName, "r+");
  209.   if (stream == NULL) { /* If the file could not be opened. */
  210.     
  211.     // Create a new file, and skip the first 69 bytes, 
  212.     // which are info about the current offset
  213.     stream = fopen(theErrorFileName, "w");
  214.     if(stream == NULL)
  215.     {
  216.       fprintf(stderr,"Unable to open error log file: %sn", theErrorFileName);
  217.       return -1;
  218.     }
  219.     fprintf(stream, "%s%u%s", "Current byte-offset of file-pointer is: ", 69,
  220.     "                        nnn");   
  221.     
  222.     // ...and write the error-message...
  223.     ErrorReporter::formatMessage(thrdType, thrdMessageID,
  224.  thrdProblemData, thrdObjRef,
  225.  theTraceFileName, theMessage);
  226.     fprintf(stream, "%s", theMessage);
  227.     fflush(stream);
  228.     
  229.     /* ...and finally, at the beginning of the file, 
  230.        store the position where to
  231.        start writing the next message. */
  232.     offset = ftell(stream);
  233.     // If we have not reached the maximum number of messages...
  234.     if (offset <= (maxOffset - MESSAGE_LENGTH)){
  235.       fseek(stream, 40, SEEK_SET);
  236.       // ...set the current offset...
  237.       fprintf(stream,"%d", offset);
  238.     } else {
  239.       fseek(stream, 40, SEEK_SET);
  240.       // ...otherwise, start over from the beginning.
  241.       fprintf(stream, "%u%s", 69, "             ");
  242.     }
  243.   } else {
  244.     // Go to the latest position in the file...
  245.     fseek(stream, 40, SEEK_SET);
  246.     fscanf(stream, "%u", &offset);
  247.     fseek(stream, offset, SEEK_SET);
  248.     
  249.     // ...and write the error-message there...
  250.     ErrorReporter::formatMessage(thrdType, thrdMessageID,
  251.  thrdProblemData, thrdObjRef,
  252.  theTraceFileName, theMessage);
  253.     fprintf(stream, "%s", theMessage);
  254.     fflush(stream);
  255.     
  256.     /* ...and finally, at the beginning of the file, 
  257.        store the position where to
  258.        start writing the next message. */
  259.     offset = ftell(stream);
  260.     
  261.     // If we have not reached the maximum number of messages...
  262.     if (offset <= (maxOffset - MESSAGE_LENGTH)){
  263.       fseek(stream, 40, SEEK_SET);
  264.       // ...set the current offset...
  265.       fprintf(stream,"%d", offset);
  266.     } else {
  267.       fseek(stream, 40, SEEK_SET);
  268.       // ...otherwise, start over from the beginning.
  269.       fprintf(stream, "%u%s", 69, "             ");
  270.     }
  271.   }
  272.   fflush(stream);
  273.   fclose(stream);
  274.   
  275.   if (theTraceFileName) {
  276.     // Open the tracefile...
  277.     FILE *jamStream = fopen(theTraceFileName, "w");
  278.   
  279.     //  ...and "dump the jam" there.
  280.     //  ErrorReporter::dumpJam(jamStream);
  281.     if(thrdTheEmulatedJam != 0){
  282.       dumpJam(jamStream, thrdTheEmulatedJamIndex, thrdTheEmulatedJam);
  283.     }
  284.   
  285.     /* Dont print the jobBuffers until a way to copy them, 
  286.        like the other variables,
  287.        is implemented. Otherwise when NDB keeps running, 
  288.        with this function running
  289.        in the background, the jobBuffers will change during runtime. And when
  290.        they're printed here, they will not be correct anymore.
  291.     */
  292.     globalScheduler.dumpSignalMemory(jamStream);
  293.   
  294.     fclose(jamStream);
  295.   }
  296.   return 0;
  297. }
  298. void 
  299. dumpJam(FILE *jamStream, 
  300. Uint32 thrdTheEmulatedJamIndex, 
  301. Uint8 thrdTheEmulatedJam[]) {
  302. #ifndef NO_EMULATED_JAM   
  303.   // print header
  304.   const int maxaddr = 8;
  305.   fprintf(jamStream, "JAM CONTENTS up->down left->right ?=not block entryn");
  306.   fprintf(jamStream, "%-7s ", "BLOCK");
  307.   for (int i = 0; i < maxaddr; i++)
  308.     fprintf(jamStream, "%-6s ", "ADDR");
  309.   fprintf(jamStream, "n");
  310.   // treat as array of Uint32
  311.   const Uint32 *base = (Uint32 *)thrdTheEmulatedJam;
  312.   const int first = thrdTheEmulatedJamIndex / sizeof(Uint32); // oldest
  313.   int cnt, idx;
  314.   // look for first block entry
  315.   for (cnt = 0, idx = first; cnt < EMULATED_JAM_SIZE; cnt++, idx++) {
  316.     if (idx >= EMULATED_JAM_SIZE)
  317.       idx = 0;
  318.     const Uint32 aJamEntry = base[idx];
  319.     if (aJamEntry > (1 << 20))
  320.       break;
  321.   }
  322.   // 1. if first entry is a block entry, it is printed in the main loop
  323.   // 2. else if any block entry exists, the jam starts in an unknown block
  324.   // 3. else if no block entry exists, the block is theEmulatedJamBlockNumber
  325.   // a "?" indicates first addr is not a block entry
  326.   if (cnt == 0)
  327.     ;
  328.   else if (cnt < EMULATED_JAM_SIZE)
  329.     fprintf(jamStream, "%-7s?", "");
  330.   else {
  331.     const Uint32 aBlockNumber = theEmulatedJamBlockNumber;
  332.     const char *aBlockName = getBlockName(aBlockNumber);
  333.     if (aBlockName != 0)
  334.       fprintf(jamStream, "%-7s?", aBlockName);
  335.     else
  336.       fprintf(jamStream, "0x%-5X?", aBlockNumber);
  337.   }
  338.   // loop over all entries
  339.   int cntaddr = 0;
  340.   for (cnt = 0, idx = first; cnt < EMULATED_JAM_SIZE; cnt++, idx++) {
  341.     globalData.incrementWatchDogCounter(4); // watchdog not to kill us ?
  342.     if (idx >= EMULATED_JAM_SIZE)
  343.       idx = 0;
  344.     const Uint32 aJamEntry = base[idx];
  345.     if (aJamEntry > (1 << 20)) {
  346.       const Uint32 aBlockNumber = aJamEntry >> 20;
  347.       const char *aBlockName = getBlockName(aBlockNumber);
  348.       if (cnt > 0)
  349.   fprintf(jamStream, "n");
  350.       if (aBlockName != 0)
  351. fprintf(jamStream, "%-7s ", aBlockName);
  352.       else
  353. fprintf(jamStream, "0x%-5X ", aBlockNumber);
  354.       cntaddr = 0;
  355.     }
  356.     if (cntaddr == maxaddr) {
  357.       fprintf(jamStream, "n%-7s ", "");
  358.       cntaddr = 0;
  359.     }
  360.     fprintf(jamStream, "%06u ", aJamEntry & 0xFFFFF);
  361.     cntaddr++;
  362.   }
  363.   fprintf(jamStream, "n");
  364.   fflush(jamStream);
  365. #endif // ifndef NO_EMULATED_JAM
  366. }