//------------------------------------------------------------------------------ // Desc: Checks a database for corruptions // // Tabs: 3 // // Copyright (c) 1992-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // 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, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: checkdb.cpp 3129 2006-01-25 11:46:17 -0700 (Wed, 25 Jan 2006) ahodgkinson $ //------------------------------------------------------------------------------ #include "flaimsys.h" #include "sharutil.h" #define UTIL_ID "CHECKDB" #define LABEL_COLUMN 5 #define VALUE_COLUMN 30 #define LOG_FILE_ROW 1 #define SOURCE_ROW 2 #define DATA_DIR_ROW 3 #define RFL_DIR_ROW 4 #define CACHE_USED_ROW 5 #define ECACHE_USED_ROW 6 #define DOING_ROW 7 #define FILE_SIZE_ROW 8 #define AMOUNT_DONE_ROW 9 #define TOTAL_DOM_NODES_ROW 10 #define DOM_LINKS_VERIFIED_ROW 11 #define TOTAL_BROKEN_LINKS_ROW 12 #define TOTAL_KEYS_ROW 13 #define TOTAL_DUPS_ROW 14 #define TOTAL_KEYS_EXAM_ROW 15 #define BAD_IXREF_ROW 16 #define MISSING_IXREF_ROW 17 #define CONFLICT_ROW 18 #define CORRUPT_ROW 19 #define TOTAL_CORRUPT_ROW 20 #define REPAIR_ROW 21 #define OLD_VIEW_ROW 22 #define MISMATCH_ROW 23 #define MAX_LOG_BUFF 2048 #define MISMATCH_READ_ERR 0 #define MISMATCH_ERROR_CODE 1 #define MISMATCH_ERR_LOCALE 2 #define MISMATCH_LF_NUMBER 3 #define MISMATCH_LF_NAME 4 #define MISMATCH_LF_TYPE 5 #define MISMATCH_LF_LEVEL 6 #define MISMATCH_BLK_ADDRESS 7 #define MISMATCH_PARENT_ADDRESS 8 #define MISMATCH_ELM_OFFSET 9 #define MISMATCH_DRN 10 #define MISMATCH_ELM_REC_OFFSET 11 #define MISMATCH_FIELD_NUM 12 #define MISMATCH_ERR_NOT_LOGGED 13 #define SCREEN_REFRESH_RATE 100 /******************************************************************** Desc: *********************************************************************/ class F_LocalCheckStatus : public IF_DbCheckStatus { public: F_LocalCheckStatus() { m_uiLastRefresh = 0; } RCODE FLMAPI reportProgress( XFLM_PROGRESS_CHECK_INFO * pProgCheck); RCODE FLMAPI reportCheckErr( XFLM_CORRUPT_INFO * pCorruptInfo, FLMBOOL * pbFix); private: FLMUINT m_uiLastRefresh; }; FSTATIC FLMBOOL CheckDatabase( void); FSTATIC FLMBOOL DoCheck( void); FSTATIC void CheckShowHelp( FLMBOOL bShowFullUsage); FSTATIC FLMBOOL GetParams( FLMINT iArgC, char ** ppszArgV); FSTATIC void OutLabel( FLMUINT uiCol, FLMUINT uiRow, const char * pszLabel, const char * pszValue, FLMUINT64 ui64NumValue, FLMBOOL bLogIt); FSTATIC void OutLine( const char * pszString); FSTATIC void LogFlush( void); FSTATIC void LogString( const char * pszString); FSTATIC void DisplayValue( FLMUINT uiRow, const char * pszValue); FSTATIC void DisplayNumValue( FLMUINT uiRow, FLMUINT64 ui64Number); FSTATIC void OutValue( const char * pszLabel, const char * pszValue); FSTATIC void OutUINT( const char * pszLabel, FLMUINT uiNum); FSTATIC void OutUINT64( const char * pszLabel, FLMUINT64 ui64Num); FSTATIC void OutBlkHeader( void); FSTATIC void OutOneBlockStat( const char * pszLabel, FLMUINT uiBlockSize, FLMUINT64 ui64KeyCount, FLMUINT64 ui64BytesUsed, FLMUINT64 ui64ElementCount, FLMUINT64 ui64ContElementCount, FLMUINT64 ui64ContElmBytes, FLMUINT uiBlockCount, FLMINT iLastError, FLMUINT uiNumErrors); FSTATIC void OutLogicalFile( IF_DbInfo * pDbInfo, FLMUINT uiIndex); FSTATIC void PrintInfo( IF_DbInfo * pDbInfo); FSTATIC FLMUINT CheckShowError( const char * pszMessage, FLMBOOL bLogIt); FSTATIC RCODE GetUserInput( void); FSTATIC void LogStr( FLMUINT uiIndent, const char * pszStr); FSTATIC void LogCorruptError( XFLM_CORRUPT_INFO * pCorrupt); FSTATIC void LogKeyError( XFLM_CORRUPT_INFO * pCorrupt); FSTATIC FLMBOOL DisplayField( IF_DataVector * ifpKey, FLMUINT uiElementNumber, FLMUINT uiStartCol, FLMUINT uiLevelOffset); FSTATIC FLMBOOL NumToName( FLMUINT uiNum, FLMUINT uiType, char * pszBuf); FLMBOOL gv_bShutdown = FALSE; static IF_FileHdl * gv_pLogFile = NULL; static IF_DbInfo * gv_pDbInfo = NULL; static F_Db * gv_pDb = NULL; static F_NameTable * gv_pNameTable = NULL; static FLMUINT gv_uiMaxRow; static char gv_szLogFileName[ F_PATH_MAX_SIZE]; static char gv_szTmpDir[ F_PATH_MAX_SIZE]; static char gv_szLastError[ 256]; static FLMUINT gv_uiLineCount; static char gv_szDbFileName[ F_PATH_MAX_SIZE]; static char gv_szDataDir[ F_PATH_MAX_SIZE]; static char gv_szRflDir[ F_PATH_MAX_SIZE]; static char * gv_pszLogBuffer = NULL; static FLMUINT64 gv_ui64FileSize; static FLMUINT64 gv_ui64BytesDone; static FLMUINT gv_uiCorruptCount; static FLMUINT gv_uiRepairCount; static FLMUINT gv_uiTotalCorruptions; static FLMUINT gv_uiOldViewCount; static FLMUINT gv_uiMismatchCount; static FLMUINT gv_uiLogBufferCount = 0; static FLMBOOL gv_bMultiplePasses = FALSE; static FLMBOOL gv_bBatchMode; static FLMBOOL gv_bContinue; static FLMBOOL gv_bStartUpdate = FALSE; static FLMBOOL gv_bRepairCorruptions = FALSE; static FLMBOOL gv_bDoLogicalCheck = FALSE; static FLMBOOL gv_bLoggingEnabled; static FLMBOOL gv_bShowStats; static FLMBOOL gv_bRunning; static FLMBOOL gv_bPauseBeforeExiting = FALSE; static FLMBOOL gv_bSkipDomLinkVerify = FALSE; static char gv_szPassword[256]; static IF_DbSystem * gv_pDbSystem = NULL; #ifdef FLM_WATCOM_NLM #define main nlm_main #endif /******************************************************************** Desc: *********************************************************************/ extern "C" int main( int iArgC, char ** ppszArgV) { int iResCode = 0; F_Pool logPool; logPool.poolInit( 1024); gv_bBatchMode = FALSE; gv_bShutdown = FALSE; gv_bRunning = TRUE; gv_szLastError[ 0] = '\0'; if( RC_BAD( FlmAllocDbSystem( &gv_pDbSystem))) { f_conStrOut( "\nCould not initialize FLAIM.\n"); goto Exit; } f_conInit( 0xFFFF, 0xFFFF, "FLAIM Database Check"); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conDrawBorder(); f_conClearScreen( 0, 0); f_conGetScreenSize( NULL, &gv_uiMaxRow); if (RC_BAD( logPool.poolAlloc( MAX_LOG_BUFF, (void **)&gv_pszLogBuffer))) { f_conStrOut( "\nFailed to allocatae memory pool\n"); goto Exit; } if( GetParams( iArgC, ppszArgV)) { if (!DoCheck()) { iResCode = 1; } } logPool.poolReset( NULL); if( (gv_bPauseBeforeExiting) && (!gv_bShutdown)) { f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_RED, FLM_WHITE); if( gv_szLastError[ 0] != '\0') { f_conStrOut( gv_szLastError); } f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conStrOut( "Press any character to exit CHECKDB: "); for (;;) { if( gv_bShutdown) { break; } if( f_conHaveKey()) { f_conGetKey(); break; } } } Exit: if (gv_pDbInfo) { gv_pDbInfo->Release(); } logPool.poolFree(); f_conExit(); if( gv_pDbSystem) { gv_pDbSystem->Release(); } gv_bRunning = FALSE; return( iResCode); } /******************************************************************** Desc: Check the database... *********************************************************************/ FSTATIC FLMBOOL CheckDatabase( void) { RCODE rc = NE_XFLM_OK; FLMUINT uiStatus; char szTmpBuf[ 100]; FLMUINT uiCheckFlags; FLMBOOL bOk = TRUE; IF_DbCheckStatus * pDbCheckStatus = NULL; // Open the database - so we can have access to its name table if (!gv_pDb) { if( RC_BAD( rc = gv_pDbSystem->dbOpen( gv_szDbFileName, gv_szDataDir, gv_szRflDir, gv_szPassword, XFLM_ALLOW_LIMITED_MODE, (IF_Db **)&gv_pDb))) { f_sprintf( szTmpBuf, "Error opening database: 0x%04X", (unsigned)rc); CheckShowError( szTmpBuf, TRUE); bOk = FALSE; goto Exit; } } if (gv_pNameTable) { gv_pNameTable->Release(); gv_pNameTable = NULL; } (void)gv_pDb->getNameTable( &gv_pNameTable); gv_uiCorruptCount = 0; gv_ui64BytesDone = 0; gv_ui64FileSize = 0; gv_uiOldViewCount = 0; f_conSetBackFore( FLM_BLUE, FLM_WHITE); if (gv_bLoggingEnabled) { LogString( NULL); LogString( NULL); LogString( NULL); LogString( "=========================================================================="); LogString( "CHECK PARAMETERS:"); } OutLabel( LABEL_COLUMN, SOURCE_ROW, "Database", gv_szDbFileName, 0, TRUE); OutLabel( LABEL_COLUMN, DATA_DIR_ROW, "Data Files Dir.", gv_szDataDir [0] ? &gv_szDataDir [0] : "", 0, TRUE); OutLabel( LABEL_COLUMN, RFL_DIR_ROW, "RFL Files Dir.", gv_szRflDir [0] ? &gv_szRflDir [0] : "", 0, TRUE); OutLabel( LABEL_COLUMN, LOG_FILE_ROW, "Log File", (gv_szLogFileName[ 0]) ? &gv_szLogFileName[ 0] : "", 0, FALSE); OutLabel( LABEL_COLUMN, CACHE_USED_ROW, "Cache Bytes Used", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, ECACHE_USED_ROW, "Ext. Cache Bytes Used", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, DOING_ROW, "Doing", "Opening Database File", 0, FALSE); OutLabel( LABEL_COLUMN, FILE_SIZE_ROW, "File Size", NULL, (FLMUINT)gv_ui64FileSize, FALSE); OutLabel( LABEL_COLUMN, CORRUPT_ROW, "File Corruptions", NULL, gv_uiCorruptCount, FALSE); OutLabel( LABEL_COLUMN, TOTAL_CORRUPT_ROW, "Total Corruptions", NULL, gv_uiTotalCorruptions, FALSE); OutLabel( LABEL_COLUMN, OLD_VIEW_ROW, "Old View Count", NULL, gv_uiOldViewCount, FALSE); OutLabel( LABEL_COLUMN, MISMATCH_ROW, "Mismatch Count", NULL, gv_uiMismatchCount, FALSE); OutLabel( LABEL_COLUMN, REPAIR_ROW, "Problems Repaired", NULL, gv_uiRepairCount, FALSE); OutLabel( LABEL_COLUMN, TOTAL_KEYS_ROW, "Total Index Keys", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, TOTAL_DUPS_ROW, "Total Duplicate Keys", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, CONFLICT_ROW, "Key Conflicts", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, TOTAL_KEYS_EXAM_ROW, "Num. Keys Checked", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, BAD_IXREF_ROW, "Invalid Index Keys", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, MISSING_IXREF_ROW, "Missing Index Keys", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, TOTAL_DOM_NODES_ROW, "Total DOM Nodes", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, DOM_LINKS_VERIFIED_ROW, "DOM Links Verified", NULL, 0, FALSE); OutLabel( LABEL_COLUMN, TOTAL_BROKEN_LINKS_ROW, "DOM Links Broken", NULL, 0, FALSE); if( gv_bLoggingEnabled) { LogString( NULL); LogString( "CHECK DETAILED RESULTS:"); LogString( NULL); } uiCheckFlags = 0; if( gv_bRepairCorruptions == TRUE) { uiCheckFlags |= XFLM_ONLINE; } if( gv_bDoLogicalCheck == TRUE) { uiCheckFlags |= XFLM_DO_LOGICAL_CHECK; } if (gv_bSkipDomLinkVerify) { uiCheckFlags |= XFLM_SKIP_DOM_LINK_CHECK; } if (RC_OK( rc)) { F_LocalCheckStatus dbCheckStatus; rc = gv_pDbSystem->dbCheck( gv_szDbFileName, gv_szDataDir, gv_szRflDir, NULL, uiCheckFlags, &gv_pDbInfo, &dbCheckStatus); } if( rc == NE_XFLM_FAILURE) { f_sprintf( szTmpBuf, "User pressed ESCAPE, check halted"); gv_bShutdown = TRUE; } else { f_sprintf( szTmpBuf, "RETURN CODE: 0x%04X", (unsigned)rc); } uiStatus = CheckShowError( szTmpBuf, TRUE); if( ((uiStatus != FKB_ESCAPE) || (gv_bLoggingEnabled)) && (gv_bShowStats) && ((rc == NE_XFLM_OK) || (rc == NE_XFLM_DATA_ERROR) || (rc == NE_XFLM_TRANS_ACTIVE))) { PrintInfo( gv_pDbInfo); } if( gv_bLoggingEnabled) { LogString( NULL); LogFlush(); } Exit: if( gv_pNameTable) { gv_pNameTable->Release(); gv_pNameTable = NULL; } if( gv_pDb) { gv_pDb->Release(); } if (pDbCheckStatus) { pDbCheckStatus->Release(); } return( bOk); } /******************************************************************** Desc: Function to coordinate check of the database. *********************************************************************/ FSTATIC FLMBOOL DoCheck( void) { RCODE rc = NE_XFLM_OK; FLMBOOL bOk = TRUE; char szTmpBuf[ 100]; IF_FileSystem * pFileSystem = NULL; if( RC_BAD( rc = FlmGetFileSystem( &pFileSystem))) { goto Exit; } f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, 0); gv_bContinue = TRUE; gv_uiLineCount = 0; gv_bLoggingEnabled = FALSE; gv_uiCorruptCount = 0; gv_uiTotalCorruptions = 0; gv_uiRepairCount = 0; gv_uiMismatchCount = 0; gv_uiLogBufferCount = 0; if( gv_szLogFileName[ 0]) { pFileSystem->deleteFile( gv_szLogFileName); if( RC_OK( rc = pFileSystem->createFile( gv_szLogFileName, FLM_IO_RDWR | FLM_IO_SH_DENYNONE, &gv_pLogFile))) { gv_bLoggingEnabled = TRUE; } else { f_sprintf( szTmpBuf, "Error creating log file: 0x%04X", (unsigned)rc); CheckShowError( szTmpBuf, FALSE); bOk = FALSE; goto Exit; } } f_conSetCursorType( FLM_CURSOR_INVISIBLE); for( ;;) { // Check the database... if( !CheckDatabase()) { bOk = FALSE; break; } if( (!gv_bMultiplePasses) || (gv_bShutdown)) { break; } } f_conSetCursorType( FLM_CURSOR_UNDERLINE); if( gv_bLoggingEnabled) { LogFlush(); gv_pLogFile->Release(); gv_pLogFile = NULL; } Exit: if( pFileSystem) { pFileSystem->Release(); } return( bOk); } /******************************************************************** Desc: Show the help screen. *********************************************************************/ FSTATIC void CheckShowHelp( FLMBOOL bShowFullUsage ) { f_conStrOut( "\n"); if (bShowFullUsage) { f_conStrOut( "Usage: checkdb [Options]\n"); } else { f_conStrOut( "Parameters: [Options]\n\n"); } f_conStrOut( " FileName = Name of database to check.\n"); f_conStrOut( " Options\n"); f_conStrOut( " -b = Run in Batch Mode.\n"); f_conStrOut( " -c = Repair logical corruptions.\n"); f_conStrOut( " -d = Display/log detailed statistics.\n"); f_conStrOut( " -dr = RFL directory.\n"); f_conStrOut( " -dd = Data directory.\n"); f_conStrOut( " -i = Perform a logical (index) check.\n"); f_conStrOut( " -l = Log detailed information to .\n"); f_conStrOut( " -m = Multiple passes (continuous check).\n"); f_conStrOut( " -o = Output binary log information to .\n"); f_conStrOut( " -p = Pause before exiting.\n"); f_conStrOut( " -s = Skip DOM link verification.\n"); f_conStrOut( " -t = Temporary directory.\n"); f_conStrOut( " -u = Run check in an update transaction.\n"); f_conStrOut( " -v = Verify binary log information in . NOTE:\n"); f_conStrOut( " The -v and -o options cannot both be specified.\n"); f_conStrOut( " -a = Database password.\n"); f_conStrOut( " -? = A '?' anywhere in the command line will cause this\n"); f_conStrOut( " screen to be displayed.\n"); f_conStrOut( "Options may be specified anywhere in the command line.\n"); } /******************************************************************** Desc: *********************************************************************/ FSTATIC FLMBOOL GetParams( FLMINT iArgC, char ** ppszArgV ) { #define MAX_ARGS 30 FLMUINT uiLoop; char szTmpBuf[ 100]; char * pszTmp; char * ppszArgs[ MAX_ARGS]; char szCommandBuffer[ 300]; gv_szDbFileName [0] = '\0'; gv_szDataDir [0] = '\0'; gv_szRflDir [0] = '\0'; gv_szLogFileName[ 0] = '\0'; gv_szTmpDir[ 0] = '\0'; gv_bShowStats = FALSE; gv_szPassword[0] = '\0'; /* Ask the user to enter parameters if none were entered on the command line. */ if( iArgC < 2) { for( ;;) { f_conStrOut( "CheckDB Params (enter ? for help): "); szCommandBuffer[ 0] = '\0'; f_conLineEdit( szCommandBuffer, sizeof( szCommandBuffer) - 1); if( gv_bShutdown) { return( FALSE); } if( f_stricmp( szCommandBuffer, "?") == 0) { CheckShowHelp( FALSE); } else { break; } } flmUtilParseParams( szCommandBuffer, MAX_ARGS, &iArgC, &ppszArgs [1]); ppszArgs [0] = ppszArgV [0]; iArgC++; ppszArgV = &ppszArgs [0]; } uiLoop = 1; while( uiLoop < (FLMUINT)iArgC) { pszTmp = ppszArgV[ uiLoop]; /* See if they specified an option */ #ifdef FLM_UNIX if( *pszTmp == '-') #else if( (*pszTmp == '-') || (*pszTmp == '/')) #endif { pszTmp++; if( (*pszTmp == 'l') || (*pszTmp == 'L')) { pszTmp++; if( *pszTmp) { f_strcpy( gv_szLogFileName, pszTmp); } else { if( CheckShowError( "Log file name not specified in parameter", FALSE) == FKB_ESCAPE) { return( FALSE); } } } else if( (*pszTmp == 't') || (*pszTmp == 'T')) { pszTmp++; if( *pszTmp) { f_strcpy( gv_szTmpDir, pszTmp); } else { if( CheckShowError( "Temporary directory not specified in parameter", FALSE) == FKB_ESCAPE) { return( FALSE); } } } else if( (*pszTmp == 'd') || (*pszTmp == 'D')) { pszTmp++; if (!(*pszTmp)) { gv_bShowStats = TRUE; } else if (*pszTmp == 'r' || *pszTmp == 'R') { f_strcpy( gv_szRflDir, pszTmp + 1); } else if (*pszTmp == 'd' || *pszTmp == 'D') { f_strcpy( gv_szDataDir, pszTmp + 1); } else { f_sprintf( szTmpBuf, "Invalid option %s", pszTmp - 1); if( CheckShowError( szTmpBuf, FALSE) == FKB_ESCAPE) { return( FALSE); } } } else if (*pszTmp == 'a' || *pszTmp == 'A') { f_strcpy( gv_szPassword, pszTmp + 1); } else if (f_stricmp( pszTmp, "B") == 0) { gv_bBatchMode = TRUE; } else if (f_stricmp( pszTmp, "C") == 0) { gv_bRepairCorruptions = TRUE; } else if (f_stricmp( pszTmp, "I") == 0) { gv_bDoLogicalCheck = TRUE; } else if (f_stricmp( pszTmp, "M") == 0) { gv_bMultiplePasses = TRUE; } else if (f_stricmp( pszTmp, "P") == 0) { gv_bPauseBeforeExiting = TRUE; } else if (f_stricmp( pszTmp, "S") == 0) { gv_bSkipDomLinkVerify = TRUE; } else if (f_stricmp( pszTmp, "U") == 0) { gv_bStartUpdate = TRUE; } else if (f_stricmp( pszTmp, "?") == 0 || f_stricmp( pszTmp, "HELP") == 0) { CheckShowHelp( TRUE); gv_bPauseBeforeExiting = TRUE; return( FALSE); } else { f_sprintf( szTmpBuf, "Invalid option %s", pszTmp); if( CheckShowError( szTmpBuf, FALSE) == FKB_ESCAPE) { return( FALSE); } } } else if( f_stricmp( pszTmp, "?") == 0) { Show_Help: CheckShowHelp( TRUE); gv_bPauseBeforeExiting = TRUE; return( FALSE); } else if( !gv_szDbFileName[ 0]) { f_strcpy( gv_szDbFileName, pszTmp); } uiLoop++; } if( !gv_szDbFileName[ 0]) { goto Show_Help; } else { return( TRUE); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void LogFlush( void ) { FLMUINT uiBytesWritten; if( gv_uiLogBufferCount) { gv_pLogFile->write( FLM_IO_CURRENT_POS, gv_uiLogBufferCount, (FLMBYTE *)gv_pszLogBuffer, &uiBytesWritten); gv_uiLogBufferCount = 0; } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void LogString( const char * pszString) { FLMUINT uiLen; FLMUINT uiLoop; if( (gv_bLoggingEnabled) && (gv_pszLogBuffer != NULL)) { uiLen = (FLMUINT)((pszString != NULL) ? (FLMUINT)(f_strlen( pszString)) : 0); for( uiLoop = 0; uiLoop < uiLen; uiLoop++) { gv_pszLogBuffer[ gv_uiLogBufferCount++] = *pszString++; if( gv_uiLogBufferCount == MAX_LOG_BUFF) { LogFlush(); } } gv_pszLogBuffer[ gv_uiLogBufferCount++] = '\r'; if( gv_uiLogBufferCount == MAX_LOG_BUFF) { LogFlush(); } gv_pszLogBuffer[ gv_uiLogBufferCount++] = '\n'; if( gv_uiLogBufferCount == MAX_LOG_BUFF) { LogFlush(); } } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutLine( const char * pszBuf) { FLMUINT uiChar; if( gv_bLoggingEnabled) { LogString( pszBuf); } if( !gv_bBatchMode) { if( gv_bContinue) { if( gv_uiLineCount == 20) { f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conSetBackFore( FLM_RED, FLM_WHITE); f_conStrOut( "Press: ESC to quit, anything else to continue"); for( ;;) { if( gv_bShutdown) { uiChar = FKB_ESCAPE; break; } else if( f_conHaveKey()) { uiChar = f_conGetKey(); break; } } if( uiChar == FKB_ESCAPE) { gv_bContinue = FALSE; } else { f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, 0); } gv_uiLineCount = 0; } } if( gv_bContinue) { f_conStrOutXY( pszBuf, 0, gv_uiLineCount); gv_uiLineCount++; } } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutValue( const char * pszLabel, const char * pszValue) { char szTmpBuf[ 100]; f_strcpy( szTmpBuf, "...................................... "); f_strcpy( &szTmpBuf[ f_strlen( szTmpBuf)], pszValue); f_memcpy( szTmpBuf, pszLabel, (FLMSIZET)f_strlen( pszLabel)); OutLine( szTmpBuf); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutUINT( const char * pszLabel, FLMUINT uiNum) { char szValue [12]; if( uiNum == 0xFFFFFFFF) { f_strcpy( szValue, "0xFFFFFFFF"); } else { f_sprintf( szValue, "%u", (unsigned)uiNum); } OutValue( pszLabel, szValue); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutUINT64( const char * pszLabel, FLMUINT64 ui64Num) { char szValue [24]; if( ui64Num == (FLMUINT64)-1) { f_strcpy( szValue, "0xFFFFFFFFFFFFFFFF"); } else { f_sprintf( szValue, "%I64u", ui64Num); } OutValue( pszLabel, szValue); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutBlkHeader( void) { OutLine( " Blk Type Blk Count Total Bytes Bytes Used Prcnt Element Cnt Avg Elem"); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutOneBlockStat( const char * pszLabel, FLMUINT uiBlockSize, FLMUINT64 ui64KeyCount, FLMUINT64 ui64BytesUsed, FLMUINT64 ui64ElementCount, FLMUINT64 ui64ContElementCount, FLMUINT64 ui64ContElmBytes, FLMUINT uiBlockCount, FLMINT iLastError, FLMUINT uiNumErrors) { char szTmpBuf[ 100]; FLMUINT64 ui64TotalBytes; FLMUINT uiPercent; FLMUINT uiAvgElementSize; ui64TotalBytes = (FLMUINT64)uiBlockCount * (FLMUINT64)uiBlockSize; if( ui64ElementCount) { uiAvgElementSize = (FLMUINT)( ui64BytesUsed / ui64ElementCount); } else { uiAvgElementSize = 0; } if( ui64BytesUsed > 40000000) { uiPercent = (FLMUINT)( ui64BytesUsed / (ui64TotalBytes / 100)); } else if( ui64TotalBytes) { uiPercent = (FLMUINT)((ui64BytesUsed * 100) / ui64TotalBytes); } else { uiPercent = 0; } f_sprintf( szTmpBuf, "%-12s %10u %11u %10u %5u %11u %8u", pszLabel, (unsigned)uiBlockCount, (unsigned)ui64TotalBytes, (unsigned)ui64BytesUsed, (unsigned)uiPercent, (unsigned)ui64ElementCount, (unsigned)uiAvgElementSize); OutLine( szTmpBuf); if( ui64ContElementCount) { uiAvgElementSize = (FLMUINT)( ui64ContElmBytes / ui64ContElementCount); if( ui64ContElmBytes > 40000000) { uiPercent = (FLMUINT)( ui64ContElmBytes / (ui64TotalBytes / 100)); } else if( ui64TotalBytes) { uiPercent = (FLMUINT)((ui64ContElmBytes * 100) / ui64TotalBytes); } else { uiPercent = 0; } f_sprintf( szTmpBuf, "%-12s " "%10u %5u %11u %8u", " ContElm", (unsigned)ui64ContElmBytes, (unsigned)uiPercent, (unsigned)ui64ContElementCount, (unsigned)uiAvgElementSize); OutLine( szTmpBuf); } if( ui64KeyCount) { f_sprintf( szTmpBuf, "%-12s %10u", " KeyCnt", (unsigned)ui64KeyCount); OutLine( szTmpBuf); } if( uiNumErrors) { f_strcpy( szTmpBuf, " LAST ERROR: "); f_strcpy( &szTmpBuf[ f_strlen( szTmpBuf)], gv_pDbSystem->checkErrorToStr( iLastError)); OutLine( szTmpBuf); f_sprintf( szTmpBuf, " TOTAL ERRORS: %u", (unsigned)uiNumErrors); OutLine( szTmpBuf); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutLogicalFile( IF_DbInfo * pDbInfo, FLMUINT uiIndex ) { char szTmpBuf[ 100]; FLMUINT uiLoop; char szLfName[ 30]; FLMUINT uiLfNum; eLFileType eLfType; FLMUINT uiRootBlkAddress; FLMUINT uiNumLevels; FLMUINT64 ui64KeyCount; FLMUINT64 ui64BytesUsed; FLMUINT64 ui64ElementCount; FLMUINT64 ui64ContElementCount; FLMUINT64 ui64ContElmBytes; FLMUINT uiBlockCount; FLMINT iLastError; FLMUINT uiNumErrors; pDbInfo->getBTreeInfo( uiIndex, &uiLfNum, &eLfType, &uiRootBlkAddress, &uiNumLevels); switch( eLfType) { case XFLM_LF_COLLECTION: /* Data collection */ f_strcpy( szTmpBuf, "COLLECTION"); break; case XFLM_LF_INDEX: /* Index */ f_strcpy( szTmpBuf, "INDEX"); break; default: break; } (void)NumToName( uiLfNum, eLfType == XFLM_LF_COLLECTION ? ELM_COLLECTION_TAG : ELM_INDEX_TAG, szLfName); OutValue( szTmpBuf, szLfName); OutUINT( " Logical File Number", uiLfNum); OutUINT( " Root Block Address", uiRootBlkAddress); if (!uiNumLevels) { OutUINT( " Levels", uiNumLevels); } else { OutBlkHeader(); for( uiLoop = 0; uiLoop < uiNumLevels; uiLoop++) { f_sprintf( szTmpBuf, " Level %u", (unsigned)uiLoop); pDbInfo->getBTreeBlockStats( uiIndex, uiLoop, &ui64KeyCount, &ui64BytesUsed, &ui64ElementCount, &ui64ContElementCount, &ui64ContElmBytes, &uiBlockCount, &iLastError, &uiNumErrors); OutOneBlockStat( szTmpBuf, pDbInfo->getDbHdr()->ui16BlockSize, ui64KeyCount, ui64BytesUsed, ui64ElementCount, ui64ContElementCount, ui64ContElmBytes, uiBlockCount, iLastError, uiNumErrors); } } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void PrintInfo( IF_DbInfo * pDbInfo ) { FLMUINT uiLoop; FLMUINT uiNumLogicalFiles; FLMUINT64 ui64BytesUsed; FLMUINT64 ui64ElementCount; FLMUINT64 ui64ContElementCount; FLMUINT64 ui64ContElmBytes; FLMUINT uiBlockCount; FLMINT iLastError; FLMUINT uiNumErrors; const XFLM_DB_HDR * pDbHdr = pDbInfo->getDbHdr(); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, 0); OutUINT( "Default Language", (FLMUINT)pDbHdr->ui8DefaultLanguage); OutUINT64( "File Size", pDbInfo->getFileSize()); OutUINT( "Index Count", pDbInfo->getNumIndexes()); OutUINT( "Collection Count", pDbInfo->getNumCollections()); OutUINT( "Block Size", (FLMUINT)pDbHdr->ui16BlockSize); OutLine( "LOG HEADER"); OutUINT( " First LFH Block Address", (FLMUINT)pDbHdr->ui32FirstLFBlkAddr); OutLine( "MISCELLANEOUS BLOCK STATISTICS"); OutBlkHeader(); ui64ElementCount = 0; ui64ContElementCount = 0; ui64ContElmBytes = 0; pDbInfo->getAvailBlockStats( &ui64BytesUsed, &uiBlockCount, &iLastError, &uiNumErrors); if( uiBlockCount) { OutOneBlockStat( " Avail", (FLMUINT)pDbHdr->ui16BlockSize, 0, ui64BytesUsed, ui64ElementCount, ui64ContElementCount, ui64ContElmBytes, uiBlockCount, iLastError, uiNumErrors); } ui64ElementCount = 0; ui64ContElementCount = 0; ui64ContElmBytes = 0; pDbInfo->getLFHBlockStats( &ui64BytesUsed, &uiBlockCount, &iLastError, &uiNumErrors); if( uiBlockCount) { OutOneBlockStat( " LFH", (FLMUINT)pDbHdr->ui16BlockSize, 0, ui64BytesUsed, ui64ElementCount, ui64ContElementCount, ui64ContElmBytes, uiBlockCount, iLastError, uiNumErrors); } uiNumLogicalFiles = pDbInfo->getNumLogicalFiles(); for( uiLoop = 0; uiLoop < uiNumLogicalFiles; uiLoop++) { OutLogicalFile( pDbInfo, uiLoop); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC FLMUINT CheckShowError( const char * pszMessage, FLMBOOL bLogIt) { FLMUINT uiResKey; f_sprintf( gv_szLastError, "%s", pszMessage); if( bLogIt) { LogString( pszMessage); } if( gv_bBatchMode) { uiResKey = 0; } else { f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_RED, FLM_WHITE); f_conStrOut( pszMessage); f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conStrOut( "Press ENTER to continue, ESC to quit"); for( ;;) { if( gv_bShutdown) { uiResKey = FKB_ESCAPE; break; } else if( f_conHaveKey()) { uiResKey = f_conGetKey(); if( (uiResKey == FKB_ENTER) || (uiResKey == FKB_ESCAPE)) { break; } } } f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 2)); } return( uiResKey); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void OutLabel( FLMUINT uiCol, FLMUINT uiRow, const char * pszLabel, const char * pszValue, FLMUINT64 ui64NumValue, FLMBOOL bLogIt) { char szTmpBuf[ 100]; FLMUINT uiLoop; f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conStrOutXY( pszLabel, uiCol, uiRow); for( uiLoop = f_conGetCursorColumn(); uiLoop < VALUE_COLUMN - 1; uiLoop++) { f_conStrOut( "."); } if( pszValue != NULL) { DisplayValue( uiRow, pszValue); } else { DisplayNumValue( uiRow, ui64NumValue); } if( (bLogIt) && (gv_bLoggingEnabled)) { f_strcpy( szTmpBuf, pszLabel); f_strcpy( &szTmpBuf[ f_strlen( szTmpBuf)], ": "); if( pszValue != NULL) { f_strcpy( &szTmpBuf[ f_strlen( szTmpBuf)], pszValue); } else { f_sprintf( &szTmpBuf[ f_strlen( szTmpBuf)], "%I64u", ui64NumValue); } LogString( szTmpBuf); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void DisplayValue( FLMUINT uiRow, const char * pszValue) { f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conStrOutXY( pszValue, VALUE_COLUMN, uiRow); f_conClearLine( 255, 255); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void DisplayNumValue( FLMUINT uiRow, FLMUINT64 ui64Number) { char szTmpBuf[ 128]; f_sprintf( szTmpBuf, "%,23I64u 0x%016I64X", ui64Number, ui64Number); DisplayValue( uiRow, szTmpBuf); } /******************************************************************** Desc: *********************************************************************/ FSTATIC RCODE GetUserInput( void ) { FLMUINT uiChar; f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 1)); f_conSetBackFore( FLM_RED, FLM_WHITE); f_conStrOut( "Q,ESC=Quit, Other=Continue"); for( ;;) { if( gv_bShutdown) { uiChar = FKB_ESCAPE; break; } else if( f_conHaveKey()) { uiChar = f_conGetKey(); break; } } f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 1)); switch( uiChar) { case 'q': case 'Q': case FKB_ESCAPE: return( RC_SET( NE_XFLM_FAILURE)); default: break; } return( NE_XFLM_OK); } /******************************************************************** Desc: *********************************************************************/ RCODE F_LocalCheckStatus::reportProgress( XFLM_PROGRESS_CHECK_INFO * pProgCheck) { RCODE rc = NE_XFLM_OK; XFLM_CACHE_INFO cacheInfo; char szWhat[ 256]; char szLfName[ 128]; FLMUINT uiCurrentTime; uiCurrentTime = FLM_TIMER_UNITS_TO_MILLI( FLM_GET_TIMER()); if( (uiCurrentTime - m_uiLastRefresh < SCREEN_REFRESH_RATE) && !pProgCheck->bStartFlag) { goto Exit; } // We have exceeded our refresh interval or we have changed check phases, // therefore, we should refresh the screen. m_uiLastRefresh = uiCurrentTime; gv_pDbSystem->getCacheInfo( &cacheInfo); DisplayNumValue( CACHE_USED_ROW, cacheInfo.BlockCache.uiByteCount); DisplayNumValue( ECACHE_USED_ROW, cacheInfo.ECache.ui64TotalBytesAllocated); if( gv_bShutdown) { rc = RC_SET( NE_XFLM_FAILURE); goto Exit; } // Update the display first gv_ui64BytesDone = pProgCheck->ui64BytesExamined; DisplayNumValue( TOTAL_KEYS_ROW, pProgCheck->ui64NumKeys); DisplayNumValue( TOTAL_DUPS_ROW, pProgCheck->ui64NumDuplicateKeys); DisplayNumValue( TOTAL_KEYS_EXAM_ROW, pProgCheck->ui64NumKeysExamined); DisplayNumValue( CONFLICT_ROW, pProgCheck->ui64NumConflicts); DisplayNumValue( BAD_IXREF_ROW, pProgCheck->ui64NumKeysNotFound); DisplayNumValue( MISSING_IXREF_ROW, pProgCheck->ui64NumDocKeysNotFound); DisplayNumValue( TOTAL_DOM_NODES_ROW, pProgCheck->ui64NumDomNodes); DisplayNumValue( DOM_LINKS_VERIFIED_ROW, pProgCheck->ui64NumDomLinksVerified); DisplayNumValue( TOTAL_BROKEN_LINKS_ROW, pProgCheck->ui64NumBrokenDomLinks); DisplayNumValue( REPAIR_ROW, pProgCheck->uiNumProblemsFixed); gv_uiRepairCount = pProgCheck->uiNumProblemsFixed; if( pProgCheck->iCheckPhase != XFLM_CHECK_RS_SORT) { OutLabel( LABEL_COLUMN, AMOUNT_DONE_ROW, "Bytes Checked", NULL, gv_ui64BytesDone, FALSE); } if( pProgCheck->bStartFlag) { gv_ui64FileSize = pProgCheck->ui64FileSize; DisplayNumValue( FILE_SIZE_ROW, gv_ui64FileSize); switch( pProgCheck->iCheckPhase) { case XFLM_CHECK_LFH_BLOCKS: f_strcpy( szWhat, "LFH BLOCKS"); break; case XFLM_CHECK_B_TREE: *szLfName = '\0'; if( pProgCheck->uiLfType == XFLM_LF_INDEX) { f_strcpy( szWhat, "INDEX: "); (void)NumToName( pProgCheck->uiLfNumber, ELM_INDEX_TAG, szLfName); } else if( pProgCheck->uiLfType == XFLM_LF_COLLECTION) { f_strcpy( szWhat, "COLLECTION: "); (void)NumToName( pProgCheck->uiLfNumber, ELM_COLLECTION_TAG, szLfName); } else { f_strcpy( szWhat, "DICTIONARY: "); (void)NumToName( pProgCheck->uiLfNumber, ELM_INDEX_TAG, szLfName); } f_strcpy( &szWhat[ f_strlen( szWhat)], szLfName); f_sprintf( &szWhat[ f_strlen( szWhat)], " (%u)", (unsigned)pProgCheck->uiLfNumber); szWhat[ 50] = '\0'; break; case XFLM_CHECK_AVAIL_BLOCKS: f_strcpy( szWhat, "AVAIL BLOCKS"); break; case XFLM_CHECK_RS_SORT: f_strcpy( szWhat, "SORTING INDEX KEYS"); break; case XFLM_CHECK_DOM_LINKS: f_strcpy( szWhat, "COLLECTION: "); (void)NumToName( pProgCheck->uiLfNumber, ELM_COLLECTION_TAG, szLfName); f_strcpy( &szWhat[ f_strlen( szWhat)], szLfName); f_sprintf( &szWhat[ f_strlen( szWhat)], " (%u)", (unsigned)pProgCheck->uiLfNumber); szWhat[ 50] = '\0'; break; default: break; } szWhat[ 45] = '\0'; f_conSetBackFore( FLM_BLUE, FLM_WHITE); DisplayValue( DOING_ROW, szWhat); } else if( f_conHaveKey() && (f_conGetKey() == FKB_ESCAPE)) { f_conSetBackFore( FLM_BLUE, FLM_WHITE); f_conSetCursorPos( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_RED, FLM_WHITE); f_conStrOut( "ESCAPE key pressed.\n"); rc = GetUserInput(); f_conClearScreen( 0, (FLMUINT)(gv_uiMaxRow - 2)); f_conSetBackFore( FLM_BLUE, FLM_WHITE); goto Exit; } Exit: return rc; } RCODE F_LocalCheckStatus::reportCheckErr( XFLM_CORRUPT_INFO * pCorruptInfo, FLMBOOL * pbFix) { RCODE rc = NE_XFLM_OK; XFLM_CACHE_INFO cacheInfo; gv_pDbSystem->getCacheInfo( &cacheInfo); DisplayNumValue( CACHE_USED_ROW, cacheInfo.BlockCache.uiByteCount); DisplayNumValue( ECACHE_USED_ROW, cacheInfo.ECache.ui64TotalBytesAllocated); if( (gv_bLoggingEnabled) && ((gv_bShowStats) || (pCorruptInfo->iErrCode != FLM_OLD_VIEW))) { LogCorruptError( pCorruptInfo); } f_conSetBackFore( FLM_BLUE, FLM_WHITE); if( pCorruptInfo->iErrCode == FLM_OLD_VIEW) { gv_uiOldViewCount++; DisplayNumValue( OLD_VIEW_ROW, gv_uiOldViewCount); } else { gv_uiCorruptCount++; gv_uiTotalCorruptions++; DisplayNumValue( CORRUPT_ROW, gv_uiCorruptCount); DisplayNumValue( TOTAL_CORRUPT_ROW, gv_uiTotalCorruptions); } if (pbFix) { *pbFix = gv_bRepairCorruptions; } return( rc); } /******************************************************************** Desc: *********************************************************************/ FSTATIC void LogStr( FLMUINT uiIndent, const char * pszStr) { FLMUINT uiLoop; if( gv_bLoggingEnabled) { for( uiLoop = 0; uiLoop < uiIndent; uiLoop++) { gv_pszLogBuffer[ gv_uiLogBufferCount++] = ' '; if( gv_uiLogBufferCount == MAX_LOG_BUFF) { LogFlush(); } } LogString( pszStr); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void LogCorruptError( XFLM_CORRUPT_INFO * pCorrupt) { char szWhat[ 20]; char szTmpBuf[ 100]; switch( pCorrupt->uiErrLocale) { case XFLM_LOCALE_LFH_LIST: { LogStr( 0, "ERROR IN LFH LINKED LIST:"); break; } case XFLM_LOCALE_AVAIL_LIST: { LogStr( 0, "ERROR IN AVAIL LINKED LIST:"); break; } case XFLM_LOCALE_B_TREE: { if( pCorrupt->iErrCode == FLM_OLD_VIEW) { LogStr( 0, "OLD VIEW"); } else { if( pCorrupt->ui64ErrNodeId) { f_strcpy( szWhat, "NODE"); } else if( pCorrupt->uiErrElmOffset) { f_strcpy( szWhat, "ELEMENT"); } else if( pCorrupt->uiErrBlkAddress) { f_strcpy( szWhat, "BLOCK"); } else { f_strcpy( szWhat, "LAST BLOCK"); } f_sprintf( szTmpBuf, "BAD %s", szWhat); LogStr( 0, szTmpBuf); } // Log the logical file number, name, and type f_sprintf( szTmpBuf, "Logical File Number: %u", (unsigned)pCorrupt->uiErrLfNumber); LogStr( 2, szTmpBuf); switch( pCorrupt->uiErrLfType) { case XFLM_LF_COLLECTION: { f_strcpy( szWhat, "Collection"); break; } case XFLM_LF_INDEX: { f_strcpy( szWhat, "Index"); break; } default: { f_sprintf( szWhat, "?%u", (unsigned)pCorrupt->uiErrLfType); break; } } f_sprintf( szTmpBuf, "Logical File Type: %s", szWhat); LogStr( 2, szTmpBuf); // Log the level in the B-Tree, if known if( pCorrupt->uiErrBTreeLevel != 0xFF) { f_sprintf( szTmpBuf, "Level in B-Tree: %u", (unsigned)pCorrupt->uiErrBTreeLevel); LogStr( 2, szTmpBuf); } break; } case XFLM_LOCALE_INDEX: { f_strcpy( szWhat, "Index"); LogKeyError( pCorrupt); break; } default: { pCorrupt->uiErrLocale = 0; break; } } // Log the block address, if known if( pCorrupt->uiErrBlkAddress) { f_sprintf( szTmpBuf, "Block Address: 0x%08X (%u)", (unsigned)pCorrupt->uiErrBlkAddress, (unsigned)pCorrupt->uiErrBlkAddress); LogStr( 2, szTmpBuf); } // Log the parent block address, if known if( pCorrupt->uiErrParentBlkAddress) { if( pCorrupt->uiErrParentBlkAddress != 0xFFFFFFFF) { f_sprintf( szTmpBuf, "Parent Block Address: 0x%08X (%u)", (unsigned)pCorrupt->uiErrParentBlkAddress, (unsigned)pCorrupt->uiErrParentBlkAddress); } else { f_sprintf( szTmpBuf, "Parent Block Address: NONE, Root Block"); } LogStr( 2, szTmpBuf); } // Log the element offset, if known if( pCorrupt->uiErrElmOffset != (FLMUINT)~(0)) { f_sprintf( szTmpBuf, "Element Offset: %u", (unsigned)pCorrupt->uiErrElmOffset); LogStr( 2, szTmpBuf); } // Log the NodeId, if known if( pCorrupt->ui64ErrNodeId) { f_sprintf( szTmpBuf, "NodeId: %u", (unsigned)pCorrupt->ui64ErrNodeId); LogStr( 2, szTmpBuf); } f_strcpy( szTmpBuf, gv_pDbSystem->checkErrorToStr( pCorrupt->iErrCode)); f_sprintf( &szTmpBuf[ f_strlen( szTmpBuf)], " (%d)", (int)pCorrupt->iErrCode); LogStr( 2, szTmpBuf); LogStr( 0, NULL); if( gv_bLoggingEnabled) { gv_pLogFile->flush(); } } /******************************************************************** Desc: *********************************************************************/ FSTATIC void LogKeyError( XFLM_CORRUPT_INFO * pCorrupt) { FLMUINT uiLogItem; IF_DataVector * ifpKey = NULL; FLMUINT uiIndent; FLMUINT uiLevelOffset; char szNameBuf[ 200]; char szTmpBuf[ 200]; FLMUINT uiElementNumber; (void)NumToName( pCorrupt->uiErrLfNumber, ELM_INDEX_TAG, szNameBuf); LogString( NULL); LogString( NULL); f_sprintf( szTmpBuf, "ERROR IN INDEX: %s", szNameBuf); LogString( szTmpBuf); uiLogItem = 'K'; uiLevelOffset = 0; for( ;;) { uiIndent = 2; if( uiLogItem == 'K') { if( (ifpKey = pCorrupt->ifpErrIxKey) == NULL) { uiLogItem = 'L'; continue; } LogString( NULL); LogString( " PROBLEM KEY"); } uiElementNumber = 0; while( ifpKey->getNameId( uiElementNumber)) { DisplayField( ifpKey, uiElementNumber, uiIndent, uiLevelOffset); uiElementNumber++; } if( uiLogItem == 'L') { break; } else { uiLogItem = 'L'; } } } /*************************************************************************** Name: DisplayField Desc: This routine displays a field to the screen. *****************************************************************************/ FSTATIC FLMBOOL DisplayField( IF_DataVector * ifpKey, FLMUINT uiElementNumber, FLMUINT uiStartCol, FLMUINT uiLevelOffset ) { char szTmpBuf[ 220]; FLMUINT uiLoop; FLMUINT uiLen; FLMUINT uiBinLen; FLMUINT uiTmpLen; char * pszTmp; FLMBYTE * pucTmp; FLMBYTE ucTmpBin [80]; FLMUINT uiNum; FLMUINT uiIndent = (uiLevelOffset * 2) + uiStartCol; FLMUINT64 ui64NodeId; // Insert leading spaces to indent for level for( uiLoop = 0; uiLoop < uiIndent; uiLoop++) { szTmpBuf[ uiLoop] = ' '; } // Output level and tag if (ifpKey->isKeyComponent( uiElementNumber)) { f_sprintf( &szTmpBuf[ uiIndent], "K) "); } else { f_sprintf( &szTmpBuf[ uiIndent], "D) "); } (void)NumToName( ifpKey->getNameId( uiElementNumber), ifpKey->isAttr( uiElementNumber) ? ELM_ATTRIBUTE_TAG : ELM_ELEMENT_TAG, &szTmpBuf[ f_strlen( szTmpBuf)]); // Output what will fit of the value on the rest of the line uiLen = f_strlen( szTmpBuf); szTmpBuf[ uiLen++] = ' '; szTmpBuf[ uiLen] = 0; if (!ifpKey->getDataLength( uiElementNumber)) { goto Exit; } switch( ifpKey->getDataType( uiElementNumber)) { case XFLM_TEXT_TYPE: pszTmp = &szTmpBuf[ uiLen]; uiLen = 80 - uiLen; ifpKey->getUTF8( uiElementNumber, (FLMBYTE *)pszTmp, &uiLen); break; case XFLM_NUMBER_TYPE: ifpKey->getUINT( uiElementNumber, &uiNum); f_sprintf( &szTmpBuf [uiLen], "%u", (unsigned)uiNum); break; case XFLM_BINARY_TYPE: ifpKey->getBinary( uiElementNumber, NULL, &uiBinLen); uiTmpLen = sizeof( ucTmpBin); ifpKey->getBinary( uiElementNumber, ucTmpBin, &uiTmpLen); pucTmp = &ucTmpBin [0]; while (uiBinLen && uiLen < 77) { f_sprintf( &szTmpBuf [uiLen], "%02X ", (unsigned)*pucTmp); uiBinLen--; pucTmp++; uiLen += 3; } szTmpBuf [uiLen - 1] = 0; break; default: break; } // Get the Id to display if ((ui64NodeId = ifpKey->getID( uiElementNumber)) != 0) { uiLen = f_strlen( szTmpBuf); f_sprintf( &szTmpBuf[ uiLen], " %I64u", ui64NodeId); } // Output the line Exit: LogString( szTmpBuf); return( TRUE); } /******************************************************************** Desc: *********************************************************************/ FSTATIC FLMBOOL NumToName( FLMUINT uiNum, FLMUINT uiType, char * pszBuf ) { FLMUINT uiLen = 128; if (gv_pNameTable && RC_OK( gv_pNameTable->getFromTagTypeAndNum( gv_pDb, uiType, uiNum, NULL, pszBuf, &uiLen))) { return( TRUE); } switch (uiType) { case ELM_INDEX_TAG: { if (uiNum == XFLM_DICT_NUMBER_INDEX) { f_strcpy( pszBuf, "Dictionary Number Index"); return( TRUE); } else if (uiNum == XFLM_DICT_NAME_INDEX) { f_strcpy( pszBuf, "Dictionary Name Index"); return( TRUE); } } case ELM_COLLECTION_TAG: { if (uiNum == XFLM_DATA_COLLECTION) { f_strcpy( pszBuf, "Data Collection"); return( TRUE); } else if (uiNum == XFLM_DICT_COLLECTION) { f_strcpy( pszBuf, "Dictionary Collection"); return( TRUE); } } } f_sprintf( pszBuf, "#%u", (unsigned)uiNum); return( FALSE); }