git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@1070 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2102 lines
46 KiB
C++
2102 lines
46 KiB
C++
//------------------------------------------------------------------------------
|
|
// Desc: Checks a database for corruptions
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1992-2007 Novell, Inc. All Rights Reserved.
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; version 2.1
|
|
// of the License.
|
|
//
|
|
// This library 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
|
|
// Library Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; 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$
|
|
//------------------------------------------------------------------------------
|
|
|
|
#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 DOING_ROW 6
|
|
#define FILE_SIZE_ROW 7
|
|
#define AMOUNT_DONE_ROW 8
|
|
|
|
#define TOTAL_DOM_NODES_ROW 9
|
|
#define DOM_LINKS_VERIFIED_ROW 10
|
|
#define TOTAL_BROKEN_LINKS_ROW 11
|
|
|
|
#define TOTAL_KEYS_ROW 12
|
|
#define TOTAL_DUPS_ROW 13
|
|
#define TOTAL_KEYS_EXAM_ROW 14
|
|
#define BAD_IXREF_ROW 15
|
|
#define MISSING_IXREF_ROW 16
|
|
#define CONFLICT_ROW 17
|
|
#define CORRUPT_ROW 18
|
|
#define TOTAL_CORRUPT_ROW 19
|
|
#define REPAIR_ROW 20
|
|
#define OLD_VIEW_ROW 21
|
|
#define MISMATCH_ROW 22
|
|
|
|
#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 XFLAPI reportProgress(
|
|
XFLM_PROGRESS_CHECK_INFO * pProgCheck);
|
|
|
|
RCODE XFLAPI 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,
|
|
FLMINT32 i32LastError,
|
|
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_RING_ZERO_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]
|
|
: "<Same as DB>",
|
|
0,
|
|
TRUE);
|
|
|
|
OutLabel( LABEL_COLUMN,
|
|
RFL_DIR_ROW,
|
|
"RFL Files Dir.",
|
|
gv_szRflDir [0]
|
|
? &gv_szRflDir [0]
|
|
: "<Same as DB>",
|
|
0,
|
|
TRUE);
|
|
|
|
OutLabel( LABEL_COLUMN,
|
|
LOG_FILE_ROW,
|
|
"Log File",
|
|
(gv_szLogFileName[ 0])
|
|
? &gv_szLogFileName[ 0]
|
|
: "<NONE>",
|
|
0,
|
|
FALSE);
|
|
|
|
OutLabel( LABEL_COLUMN,
|
|
CACHE_USED_ROW,
|
|
"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 <FileName> [Options]\n");
|
|
}
|
|
else
|
|
{
|
|
f_conStrOut( "Parameters: <FileName> [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<Dir> = RFL directory.\n");
|
|
f_conStrOut(
|
|
" -dd<Dir> = Data directory.\n");
|
|
f_conStrOut(
|
|
" -i = Perform a logical (index) check.\n");
|
|
f_conStrOut(
|
|
" -l<FileName> = Log detailed information to <FileName>.\n");
|
|
f_conStrOut(
|
|
" -m = Multiple passes (continuous check).\n");
|
|
f_conStrOut(
|
|
" -o<FileName> = Output binary log information to <FileName>.\n");
|
|
f_conStrOut(
|
|
" -p = Pause before exiting.\n");
|
|
f_conStrOut(
|
|
" -s = Skip DOM link verification.\n");
|
|
f_conStrOut(
|
|
" -t<Path> = Temporary directory.\n");
|
|
f_conStrOut(
|
|
" -u = Run check in an update transaction.\n");
|
|
f_conStrOut(
|
|
" -v<FileName> = Verify binary log information in <FileName>. NOTE:\n");
|
|
f_conStrOut(
|
|
" The -v and -o options cannot both be specified.\n");
|
|
f_conStrOut(
|
|
" -a<Password> = 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,
|
|
FLMINT32 i32LastError,
|
|
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( (FLMINT)i32LastError));
|
|
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;
|
|
FLMINT32 i32LastError;
|
|
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,
|
|
&i32LastError, &uiNumErrors);
|
|
OutOneBlockStat( szTmpBuf,
|
|
pDbInfo->getDbHdr()->ui16BlockSize, ui64KeyCount,
|
|
ui64BytesUsed, ui64ElementCount, ui64ContElementCount,
|
|
ui64ContElmBytes, uiBlockCount, i32LastError, uiNumErrors);
|
|
}
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc:
|
|
*********************************************************************/
|
|
FSTATIC void PrintInfo(
|
|
IF_DbInfo * pDbInfo
|
|
)
|
|
{
|
|
FLMUINT uiLoop;
|
|
FLMUINT uiNumLogicalFiles;
|
|
FLMUINT64 ui64BytesUsed;
|
|
FLMUINT64 ui64ElementCount;
|
|
FLMUINT64 ui64ContElementCount;
|
|
FLMUINT64 ui64ContElmBytes;
|
|
FLMUINT uiBlockCount;
|
|
FLMINT32 i32LastError;
|
|
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,
|
|
&i32LastError, &uiNumErrors);
|
|
if( uiBlockCount)
|
|
{
|
|
OutOneBlockStat( " Avail",
|
|
(FLMUINT)pDbHdr->ui16BlockSize,
|
|
0, ui64BytesUsed, ui64ElementCount, ui64ContElementCount,
|
|
ui64ContElmBytes, uiBlockCount, i32LastError, uiNumErrors);
|
|
}
|
|
|
|
ui64ElementCount = 0;
|
|
ui64ContElementCount = 0;
|
|
ui64ContElmBytes = 0;
|
|
pDbInfo->getLFHBlockStats( &ui64BytesUsed, &uiBlockCount,
|
|
&i32LastError, &uiNumErrors);
|
|
if( uiBlockCount)
|
|
{
|
|
OutOneBlockStat( " LFH",
|
|
(FLMUINT)pDbHdr->ui16BlockSize,
|
|
0, ui64BytesUsed, ui64ElementCount, ui64ContElementCount,
|
|
ui64ContElmBytes, uiBlockCount, i32LastError, 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);
|
|
|
|
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->ui32NumProblemsFixed);
|
|
gv_uiRepairCount = (FLMUINT)pProgCheck->ui32NumProblemsFixed;
|
|
|
|
if( pProgCheck->i32CheckPhase != 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->i32CheckPhase)
|
|
{
|
|
case XFLM_CHECK_LFH_BLOCKS:
|
|
f_strcpy( szWhat, "LFH BLOCKS");
|
|
break;
|
|
case XFLM_CHECK_B_TREE:
|
|
*szLfName = '\0';
|
|
if( pProgCheck->ui32LfType == XFLM_LF_INDEX)
|
|
{
|
|
f_strcpy( szWhat, "INDEX: ");
|
|
(void)NumToName( pProgCheck->ui32LfNumber,
|
|
ELM_INDEX_TAG, szLfName);
|
|
}
|
|
else if( pProgCheck->ui32LfType == XFLM_LF_COLLECTION)
|
|
{
|
|
f_strcpy( szWhat, "COLLECTION: ");
|
|
(void)NumToName( pProgCheck->ui32LfNumber,
|
|
ELM_COLLECTION_TAG, szLfName);
|
|
}
|
|
else
|
|
{
|
|
f_strcpy( szWhat, "DICTIONARY: ");
|
|
(void)NumToName( pProgCheck->ui32LfNumber,
|
|
ELM_INDEX_TAG, szLfName);
|
|
}
|
|
|
|
f_strcpy( &szWhat[ f_strlen( szWhat)], szLfName);
|
|
|
|
f_sprintf( &szWhat[ f_strlen( szWhat)], " (%u)",
|
|
(unsigned)pProgCheck->ui32LfNumber);
|
|
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->ui32LfNumber,
|
|
ELM_COLLECTION_TAG, szLfName);
|
|
f_strcpy( &szWhat[ f_strlen( szWhat)], szLfName);
|
|
f_sprintf( &szWhat[ f_strlen( szWhat)], " (%u)",
|
|
(unsigned)pProgCheck->ui32LfNumber);
|
|
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);
|
|
|
|
if( (gv_bLoggingEnabled) &&
|
|
((gv_bShowStats) ||
|
|
(pCorruptInfo->i32ErrCode != FLM_OLD_VIEW)))
|
|
{
|
|
LogCorruptError( pCorruptInfo);
|
|
}
|
|
|
|
f_conSetBackFore( FLM_BLUE, FLM_WHITE);
|
|
if( pCorruptInfo->i32ErrCode == 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->ui32ErrLocale)
|
|
{
|
|
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->i32ErrCode == FLM_OLD_VIEW)
|
|
{
|
|
LogStr( 0, "OLD VIEW");
|
|
}
|
|
else
|
|
{
|
|
if( pCorrupt->ui64ErrNodeId)
|
|
{
|
|
f_strcpy( szWhat, "NODE");
|
|
}
|
|
else if( pCorrupt->ui32ErrElmOffset)
|
|
{
|
|
f_strcpy( szWhat, "ELEMENT");
|
|
}
|
|
else if( pCorrupt->ui32ErrBlkAddress)
|
|
{
|
|
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->ui32ErrLfNumber);
|
|
LogStr( 2, szTmpBuf);
|
|
|
|
switch( pCorrupt->ui32ErrLfType)
|
|
{
|
|
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->ui32ErrLfType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
f_sprintf( szTmpBuf, "Logical File Type: %s", szWhat);
|
|
LogStr( 2, szTmpBuf);
|
|
|
|
// Log the level in the B-Tree, if known
|
|
|
|
if( pCorrupt->ui32ErrBTreeLevel != 0xFF)
|
|
{
|
|
f_sprintf( szTmpBuf, "Level in B-Tree: %u",
|
|
(unsigned)pCorrupt->ui32ErrBTreeLevel);
|
|
LogStr( 2, szTmpBuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case XFLM_LOCALE_INDEX:
|
|
{
|
|
f_strcpy( szWhat, "Index");
|
|
LogKeyError( pCorrupt);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
pCorrupt->ui32ErrLocale = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Log the block address, if known
|
|
|
|
if( pCorrupt->ui32ErrBlkAddress)
|
|
{
|
|
f_sprintf( szTmpBuf, "Block Address: 0x%08X (%u)",
|
|
(unsigned)pCorrupt->ui32ErrBlkAddress,
|
|
(unsigned)pCorrupt->ui32ErrBlkAddress);
|
|
LogStr( 2, szTmpBuf);
|
|
}
|
|
|
|
// Log the parent block address, if known
|
|
|
|
if( pCorrupt->ui32ErrParentBlkAddress)
|
|
{
|
|
if( pCorrupt->ui32ErrParentBlkAddress != FLM_MAX_UINT32)
|
|
{
|
|
f_sprintf( szTmpBuf, "Parent Block Address: 0x%08X (%u)",
|
|
(unsigned)pCorrupt->ui32ErrParentBlkAddress,
|
|
(unsigned)pCorrupt->ui32ErrParentBlkAddress);
|
|
}
|
|
else
|
|
{
|
|
f_sprintf( szTmpBuf,
|
|
"Parent Block Address: NONE, Root Block");
|
|
}
|
|
LogStr( 2, szTmpBuf);
|
|
}
|
|
|
|
// Log the element offset, if known
|
|
|
|
if( pCorrupt->ui32ErrElmOffset != FLM_MAX_UINT32)
|
|
{
|
|
f_sprintf( szTmpBuf, "Element Offset: %u",
|
|
(unsigned)pCorrupt->ui32ErrElmOffset);
|
|
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( (FLMINT)pCorrupt->i32ErrCode));
|
|
f_sprintf( &szTmpBuf[ f_strlen( szTmpBuf)], " (%d)",
|
|
(int)pCorrupt->i32ErrCode);
|
|
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( (FLMUINT)pCorrupt->ui32ErrLfNumber, 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);
|
|
|
|
}
|