Files
mars-flaim/flaim/util/rebuild.cpp
2006-06-13 17:18:08 +00:00

1363 lines
32 KiB
C++

//-------------------------------------------------------------------------
// Desc: Database rebuild utility.
// 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: rebuild.cpp 12334 2006-01-23 12:45:35 -0700 (Mon, 23 Jan 2006) dsanders $
//-------------------------------------------------------------------------
#include "flaimsys.h"
#include "sharutil.h"
#define UTIL_ID "REBUILD"
#define LABEL_COLUMN 5
#define VALUE_COLUMN 35
#define PARAM_ROW 1
#define SOURCE_ROW (PARAM_ROW + 1)
#define SOURCE_DATA_DIR_ROW (SOURCE_ROW + 1)
#define DEST_ROW (SOURCE_DATA_DIR_ROW + 1)
#define DEST_DATA_DIR_ROW (DEST_ROW + 1)
#define DEST_RFL_ROW (DEST_DATA_DIR_ROW + 1)
#define DICT_ROW (DEST_RFL_ROW + 1)
#define CACHE_ROW (DICT_ROW + 1)
#define LOG_FILE_ROW (CACHE_ROW + 1)
#define DOING_ROW (LOG_FILE_ROW + 1)
#define DB_SIZE_ROW (DOING_ROW + 1)
#define BYTES_DONE_ROW (DB_SIZE_ROW + 1)
#define TOTAL_REC_ROW (BYTES_DONE_ROW + 1)
#define RECOV_ROW (TOTAL_REC_ROW + 1)
#define DICT_RECOV_ROW (RECOV_ROW + 1)
#define MAX_LOG_BUFF 2048
FSTATIC FLMBOOL bldDoRebuild( void);
FSTATIC void bldShowResults(
const char * pucFuncName,
RCODE rc,
FLMUINT uiTotalRecords,
FLMUINT uiRecordsRecovered,
FLMUINT uiDictRecordsRecovered);
FSTATIC void bldShowHelp( void);
FSTATIC FLMBOOL bldGetParams(
FLMINT iArgC,
const char ** ppszArgV);
FSTATIC FLMBOOL bldParseHdrInfo(
const char * pszBuffer);
FSTATIC void bldOutLabel(
FLMUINT uiCol,
FLMUINT uiRow,
const char * pszLabel,
const char * pszValue,
FLMUINT uiNumValue,
FLMBOOL bLogIt);
FSTATIC void bldLogFlush( void);
FSTATIC void bldLogString(
const char * pszStr);
FSTATIC void bldOutValue(
FLMUINT uiRow,
const char * pszValue);
FSTATIC void bldOutNumValue(
FLMUINT uiRow,
FLMUINT uiNumber);
FSTATIC RCODE bldGetUserInput( void);
FSTATIC void bldLogStr(
FLMUINT uiIndent,
const char * pszStr);
FSTATIC void bldLogCorruptError(
CORRUPT_INFO * pCorruptInfo);
FSTATIC RCODE bldProgFunc(
eStatusType eStatus,
void * Parm1,
void * Parm2,
void * pvAppData);
FSTATIC void bldShowError(
const char * pszMessage);
FSTATIC RCODE bldGetCreateOpts(
const char * pszFileName,
CREATE_OPTS * pCreateOpts);
FLMBOOL gv_bShutdown = FALSE;
static char * gv_pucLogBuffer = NULL;
static FLMUINT gv_uiLogBufferCount = 0;
static FLMBOOL gv_bBatchMode;
static FLMUINT64 gv_ui64DatabaseSize;
static FLMINT gv_iLastDoing;
static FLMUINT64 gv_ui64BytesDone;
static FLMUINT gv_uiTotalRecs;
static FLMUINT gv_uiRecsRecovered;
static FLMUINT gv_uiDictRecsRecovered;
static char gv_szSrcFileName[ F_PATH_MAX_SIZE];
static char gv_szSrcDataDir [F_PATH_MAX_SIZE];
static char gv_szDestFileName[ F_PATH_MAX_SIZE];
static char gv_szDestDataDir [F_PATH_MAX_SIZE];
static char gv_szDestRflDir [F_PATH_MAX_SIZE];
static char gv_szDictFileName[ F_PATH_MAX_SIZE];
static char gv_szLogFileName[ F_PATH_MAX_SIZE];
static FLMUINT gv_uiCacheSize = 30000;
static IF_FileHdl * gv_pLogFile = NULL;
static FLMBOOL gv_bLoggingEnabled;
static char * gv_pszDictPath;
static CREATE_OPTS gv_DefaultCreateOpts;
static FLMBOOL gv_bFixHdrInfo;
static FLMBOOL gv_bRunning;
static FLMBOOL gv_bPauseBeforeExiting = FALSE;
static IF_FileSystem * gv_pFileSystem = NULL;
/********************************************************************
Desc: ?
*********************************************************************/
#ifdef FLM_RING_ZERO_NLM
extern "C" int nlm_main(
#else
int main(
#endif
int iArgC,
char ** ppszArgV)
{
int iRetCode = 0;
F_Pool LogPool;
gv_bBatchMode = FALSE;
gv_bRunning = TRUE;
if( RC_BAD( FlmStartup()))
{
iRetCode = -1;
goto Exit;
}
f_conInit( 0xFFFF, 0xFFFF, "FLAIM Database Rebuild");
if( RC_BAD( FlmGetFileSystem( &gv_pFileSystem)))
{
f_conStrOut( "\nCould not allocate a file system object.\n");
goto Exit;
}
LogPool.poolInit( 1024);
if( RC_BAD( LogPool.poolAlloc( MAX_LOG_BUFF, (void **)&gv_pucLogBuffer)))
{
goto Exit;
}
if( bldGetParams( iArgC, (const char **)ppszArgV))
{
if (!bldDoRebuild())
{
iRetCode = 1;
}
}
Exit:
if (gv_bPauseBeforeExiting && !gv_bShutdown)
{
f_conStrOut( "\nPress any character to exit REBUILD: ");
for (;;)
{
if (gv_bShutdown)
{
break;
}
if (f_conHaveKey())
{
f_conGetKey();
break;
}
f_yieldCPU();
}
}
if (gv_pFileSystem)
{
gv_pFileSystem->Release();
gv_pFileSystem = NULL;
}
f_conExit();
FlmShutdown();
gv_bRunning = FALSE;
return( iRetCode);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC FLMBOOL bldDoRebuild( void)
{
RCODE rc;
FLMBOOL bOk = TRUE;
char szErrMsg[ 100];
CREATE_OPTS createOpts;
gv_ui64DatabaseSize = 0;
gv_ui64BytesDone = 0;
gv_uiDictRecsRecovered = 0;
gv_iLastDoing = -1;
gv_uiTotalRecs = 0;
gv_uiRecsRecovered = 0;
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conClearScreen( 0, 0);
gv_bLoggingEnabled = FALSE;
gv_uiLogBufferCount = 0;
if( gv_szLogFileName[ 0])
{
gv_pFileSystem->deleteFile( gv_szLogFileName);
if (RC_OK( rc = gv_pFileSystem->createFile(
gv_szLogFileName, FLM_IO_RDWR, &gv_pLogFile)))
{
gv_bLoggingEnabled = TRUE;
}
else
{
f_strcpy( szErrMsg, "Error creating log file: ");
f_strcpy( &szErrMsg[ f_strlen( szErrMsg)], FlmErrorString( rc));
bldShowError( szErrMsg);
bOk = FALSE;
goto Exit;
}
}
/* Configure FLAIM */
if (RC_BAD( rc = FlmConfig( FLM_CACHE_LIMIT,
(void *)(gv_uiCacheSize * 1024), (void *)0)))
{
f_strcpy( szErrMsg, "Error setting cache size for FLAIM share: ");
f_strcpy( &szErrMsg[ f_strlen( szErrMsg)], FlmErrorString( rc));
bldShowError( szErrMsg);
bOk = FALSE;
goto Exit;
}
f_conSetBackFore( FLM_BLACK, FLM_WHITE);
if( gv_bLoggingEnabled)
{
bldLogString( NULL);
bldLogString( NULL);
bldLogString( NULL);
bldLogString(
"==========================================================================");
bldLogString( "REBUILD PARAMETERS:");
}
f_conClearScreen( 0, PARAM_ROW);
f_conStrOutXY( "REBUILD PARAMETERS:", LABEL_COLUMN, PARAM_ROW);
bldOutLabel( LABEL_COLUMN + 2, SOURCE_ROW, "Source DB",
gv_szSrcFileName, 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, SOURCE_DATA_DIR_ROW,
"Src. Data Dir",
(gv_szSrcDataDir [0])
? &gv_szSrcDataDir [0]
: "<NONE>", 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, DEST_ROW, "Destination DB",
gv_szDestFileName, 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, DEST_DATA_DIR_ROW,
"Dest. Data Dir",
(gv_szDestDataDir [0])
? &gv_szDestDataDir [0]
: "<NONE>", 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, DEST_RFL_ROW, "Dest. RFL Dir",
(gv_szDestRflDir [0])
? &gv_szDestRflDir [0]
: "<NONE>", 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, DICT_ROW, "Dictionary File",
(gv_szDictFileName [0])
? &gv_szDictFileName [0]
: "<NONE>", 0, TRUE);
bldOutLabel( LABEL_COLUMN + 2, CACHE_ROW, "Cache (kb)", NULL,
gv_uiCacheSize, TRUE);
bldOutLabel( LABEL_COLUMN + 2, LOG_FILE_ROW, "Log File",
(gv_szLogFileName [0])
? &gv_szLogFileName [0]
: "<NONE>", 0, TRUE);
bldOutLabel( LABEL_COLUMN, DOING_ROW, "Current Action",
"Startup ", 0L, FALSE);
bldOutLabel( LABEL_COLUMN, DB_SIZE_ROW, "Database Size",
NULL, (FLMUINT)gv_ui64DatabaseSize, FALSE);
bldOutLabel( LABEL_COLUMN, BYTES_DONE_ROW, "Bytes Processed",
NULL, (FLMUINT)gv_ui64BytesDone, FALSE);
bldOutLabel( LABEL_COLUMN, TOTAL_REC_ROW, "Total Records",
NULL, gv_uiTotalRecs, FALSE);
bldOutLabel( LABEL_COLUMN, RECOV_ROW, "Records Recovered",
NULL, gv_uiRecsRecovered, FALSE);
bldOutLabel( LABEL_COLUMN, DICT_RECOV_ROW, "Dict Items Recov",
NULL, gv_uiDictRecsRecovered, FALSE);
if( gv_szDictFileName [0])
{
gv_pszDictPath = &gv_szDictFileName [0];
}
else
{
gv_pszDictPath = NULL;
}
/*
Open the database ONLY to get the createOpts.
Rebuild the exact prefix and other create options.
*/
rc = bldGetCreateOpts( gv_szSrcFileName, &createOpts);
if ((!gv_bShutdown) && (RC_OK( rc)))
{
char * pszDestRflDir;
pszDestRflDir = ((gv_szDestRflDir [0])
? &gv_szDestRflDir [0]
: NULL);
rc = FlmDbRebuild( gv_szSrcFileName, gv_szSrcDataDir,
gv_szDestFileName, gv_szDestDataDir,
pszDestRflDir,
gv_pszDictPath, &createOpts,
&gv_uiTotalRecs,
&gv_uiRecsRecovered,
bldProgFunc, NULL);
bldShowResults( "FlmDbRebuild",
rc, gv_uiTotalRecs, gv_uiRecsRecovered,
gv_uiDictRecsRecovered);
}
Exit:
if( gv_bLoggingEnabled)
{
bldLogFlush();
gv_pLogFile->Release();
gv_pLogFile = NULL;
}
return( bOk);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldShowResults(
const char * FuncName,
RCODE rc,
FLMUINT uiTotalRecords,
FLMUINT uiRecordsRecovered,
FLMUINT uiDictRecordsRecovered)
{
char szErrMsg[ 100];
if( RC_BAD( rc))
{
if( rc != FERR_FAILURE)
{
f_strcpy( szErrMsg, "Error calling ");
f_strcpy( &szErrMsg[ f_strlen( szErrMsg)], FuncName);
f_strcpy( &szErrMsg[ f_strlen( szErrMsg)], ": ");
f_strcpy( &szErrMsg[ f_strlen( szErrMsg)], FlmErrorString( rc));
bldShowError( szErrMsg);
if( gv_bLoggingEnabled)
{
bldLogString( szErrMsg);
}
}
else if( gv_bLoggingEnabled)
{
bldLogString( "REBUILD HALTED BY USER");
gv_bShutdown = TRUE;
}
}
else
{
bldOutNumValue( TOTAL_REC_ROW, uiTotalRecords);
bldOutNumValue( RECOV_ROW, uiRecordsRecovered);
bldOutNumValue( DICT_RECOV_ROW, uiDictRecordsRecovered);
if( gv_bLoggingEnabled)
{
f_sprintf( (char *)szErrMsg, "Total Records: %u", (unsigned)uiTotalRecords);
bldLogString( szErrMsg);
f_sprintf( (char *)szErrMsg, "Records Recovered: %u", (unsigned)uiRecordsRecovered);
bldLogString( szErrMsg);
f_sprintf( (char *)szErrMsg, "Dict Items Recovered: %u",
(unsigned)uiDictRecordsRecovered);
bldLogString( szErrMsg);
}
f_strcpy( szErrMsg, "Recovery completed successfully");
bldShowError( szErrMsg);
if( gv_bLoggingEnabled)
{
bldLogString( szErrMsg);
}
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldShowHelp(
void
)
{
f_conStrOut( "\n");
f_conStrOut(
"Parameters: <SourceName> <DestName> [Options]\n\n");
f_conStrOut(
"SourceName = Name of database which is to be recovered.\n");
f_conStrOut(
"DestName = Name of destination database to recover data to. Recovered\n");
f_conStrOut(
" records are put in this database.\n");
f_conStrOut(
"Options = (may be specified anywhere on command line): \n");
f_conStrOut(
" -c<n> = Cache (kilobytes) to use.\n");
f_conStrOut(
" -sd<DirName> = Data directory for source DB.\n");
f_conStrOut(
" -dc<DictName> = Dictionary file to use to create destination DB.\n");
f_conStrOut(
" -dd<DirName> = Data directory for destination DB.\n");
f_conStrOut(
" -dr<DirName> = RFL directory for destination DB.\n");
f_conStrOut(
" -l<FileName> = Log detailed information to <FileName>.\n");
f_conStrOut(
" -b = Run in Batch Mode.\n");
f_conStrOut(
" -h<HdrInfo> = Fix file header information. HdrInfo is in the format\n");
f_conStrOut(
" BlkSiz:Prod:FType:MajVer:MinVer:InitLog:LogExt:Lang:FlmVer\n");
f_conStrOut(
" -q<FileName> = Output binary log information to <FileName>.\n");
f_conStrOut(
" -v<FileName> = Verify binary log information in <FileName>. NOTE: The\n");
f_conStrOut(
" -v and -q options cannot both be specified.\n");
f_conStrOut(
" -p = Pause before exiting.\n");
f_conStrOut(
" -? = A '?' anywhere in the command line will cause this help\n");
f_conStrOut(
" screen to be displayed, with or without the leading '-'.\n");
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC FLMBOOL bldGetParams(
FLMINT iArgC,
const char ** ppszArgV)
{
#define MAX_ARGS 30
FLMUINT uiLoop;
char szErrMsg [100];
const char * pszPtr;
const char * ppszArgs[ MAX_ARGS];
char szCommandBuffer [300];
gv_szSrcFileName [0] = 0;
gv_szSrcDataDir [0] = 0;
gv_szDestFileName [0] = 0;
gv_szDestDataDir [0] = 0;
gv_szDestRflDir [0] = 0;
gv_szDictFileName [0] = 0;
gv_szLogFileName [0] = 0;
gv_bFixHdrInfo = FALSE;
gv_DefaultCreateOpts.uiBlockSize = DEFAULT_BLKSIZ;
gv_DefaultCreateOpts.uiMinRflFileSize = DEFAULT_MIN_RFL_FILE_SIZE;
gv_DefaultCreateOpts.uiMaxRflFileSize = DEFAULT_MAX_RFL_FILE_SIZE;
gv_DefaultCreateOpts.bKeepRflFiles = DEFAULT_KEEP_RFL_FILES_FLAG;
gv_DefaultCreateOpts.bLogAbortedTransToRfl = DEFAULT_LOG_ABORTED_TRANS_FLAG;
gv_DefaultCreateOpts.uiDefaultLanguage = DEFAULT_LANG;
gv_DefaultCreateOpts.uiVersionNum = FLM_CUR_FILE_FORMAT_VER_NUM;
gv_DefaultCreateOpts.uiAppMajorVer =
gv_DefaultCreateOpts.uiAppMinorVer = 0;
gv_uiCacheSize = 30000;
gv_bBatchMode = FALSE;
// Ask the user to enter parameters if none were entered on the command
// line.
if( iArgC < 2)
{
for (;;)
{
f_conStrOut( "\nRebuild Params (enter ? for help): ");
szCommandBuffer[ 0] = 0;
f_conLineEdit( szCommandBuffer, sizeof( szCommandBuffer) - 1);
if( gv_bShutdown)
{
return( FALSE);
}
if( f_stricmp( szCommandBuffer, "?") == 0)
{
bldShowHelp();
}
else
{
break;
}
}
flmUtilParseParams( szCommandBuffer, MAX_ARGS, &iArgC, &ppszArgs [1]);
ppszArgs[ 0] = ppszArgV[ 0];
iArgC++;
ppszArgV = &ppszArgs[ 0];
}
uiLoop = 1;
while (uiLoop < (FLMUINT)iArgC)
{
pszPtr = ppszArgV [uiLoop];
// See if they specified an option
#ifdef FLM_UNIX
if (*pszPtr == '-')
#else
if (*pszPtr == '-' || *pszPtr == '/')
#endif
{
pszPtr++;
if (*pszPtr == 'c' || *pszPtr == 'C')
{
gv_uiCacheSize = f_atoi( (pszPtr + 1));
}
else if (*pszPtr == 'd' || *pszPtr == 'D')
{
pszPtr++;
if (*pszPtr == 'r' || *pszPtr == 'R')
{
pszPtr++;
if (*pszPtr)
{
f_strcpy( gv_szDestRflDir, pszPtr);
}
else
{
bldShowError(
"Destination RFL directory not specified");
return( FALSE);
}
}
else if (*pszPtr == 'd' || *pszPtr == 'D')
{
pszPtr++;
if (*pszPtr)
{
f_strcpy( gv_szDestDataDir, pszPtr);
}
else
{
bldShowError(
"Destination data directory not specified");
return( FALSE);
}
}
else if (*pszPtr == 'c' || *pszPtr == 'C')
{
pszPtr++;
if (*pszPtr)
{
f_strcpy( gv_szDictFileName, pszPtr);
}
else
{
bldShowError(
"Dictionary file name not specified");
return( FALSE);
}
}
else
{
f_sprintf( szErrMsg, "Invalid option %s", pszPtr-1);
bldShowError( szErrMsg);
return( FALSE);
}
}
else if (*pszPtr == 's' || *pszPtr == 'S')
{
pszPtr++;
if (*pszPtr == 'd' || *pszPtr == 'D')
{
pszPtr++;
if (*pszPtr)
{
f_strcpy( gv_szSrcDataDir, pszPtr);
}
else
{
bldShowError(
"Source data directory not specified");
return( FALSE);
}
}
else
{
f_sprintf( szErrMsg, "Invalid option %s", pszPtr-1);
bldShowError( szErrMsg);
return( FALSE);
}
}
else if (*pszPtr == 'h' || *pszPtr == 'H')
{
pszPtr++;
if( *pszPtr)
{
if( !bldParseHdrInfo( pszPtr))
{
return( FALSE);
}
}
else
{
bldShowError( "Block sizes not specified");
return( FALSE);
}
}
else if (*pszPtr == 'l' || *pszPtr == 'L')
{
pszPtr++;
if (*pszPtr)
{
f_strcpy( gv_szLogFileName, pszPtr);
}
else
{
bldShowError( "Log file name not specified");
return( FALSE);
}
}
else if (f_stricmp( pszPtr, "P") == 0)
{
gv_bPauseBeforeExiting = TRUE;
}
else if (f_stricmp( pszPtr, "B") == 0)
{
gv_bBatchMode = TRUE;
}
else if (f_stricmp( pszPtr, "?") == 0)
{
goto Show_Help;
}
else
{
f_sprintf( szErrMsg, "Invalid option %s", pszPtr);
bldShowError( szErrMsg);
return( FALSE);
}
}
else if (f_stricmp( pszPtr, "?") == 0)
{
Show_Help:
bldShowHelp();
gv_bPauseBeforeExiting = TRUE;
return( FALSE);
}
else if (!gv_szSrcFileName[ 0])
{
f_strcpy( gv_szSrcFileName, pszPtr);
}
else if (!gv_szDestFileName[ 0])
{
f_strcpy( gv_szDestFileName, pszPtr);
}
uiLoop++;
}
if (!gv_szSrcFileName [0] || !gv_szDestFileName [0])
{
goto Show_Help;
}
return( TRUE);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC FLMBOOL bldParseHdrInfo(
const char * pucBuffer)
{
FLMUINT uiNum;
FLMBOOL bHaveParam;
CREATE_OPTS CreateOpts;
FLMUINT uiFieldNum;
f_memcpy( &CreateOpts, &gv_DefaultCreateOpts, sizeof( CREATE_OPTS));
uiFieldNum = 1;
for (;;)
{
uiNum = 0;
bHaveParam = FALSE;
while ((*pucBuffer == ' ') ||
(*pucBuffer == ':') ||
(*pucBuffer == ',') ||
(*pucBuffer == ';') ||
(*pucBuffer == '\t'))
{
pucBuffer++;
}
if( uiFieldNum == 8) // Language
{
char pszTmpBuf[ 100];
FLMUINT uiTmpLen = 0;
while ((*pucBuffer) &&
(*pucBuffer != ':') &&
(*pucBuffer != ',') &&
(*pucBuffer != ';') &&
(*pucBuffer != ' ') &&
(*pucBuffer != '\t'))
{
pszTmpBuf[ uiTmpLen++] = *pucBuffer++;
}
pszTmpBuf[ uiTmpLen] = 0;
if( uiTmpLen)
{
uiNum = f_languageToNum( pszTmpBuf);
if( (!uiNum) && (f_stricmp( pszTmpBuf, "US") != 0))
{
bldShowError( "Illegal language in header information");
return( FALSE);
}
bHaveParam = TRUE;
}
}
else
{
while( (*pucBuffer >= '0') && (*pucBuffer <= '9'))
{
uiNum *= 10;
uiNum += (FLMUINT)(*pucBuffer - '0');
pucBuffer++;
bHaveParam = TRUE;
}
}
if( ((*pucBuffer != 0) &&
(*pucBuffer != ' ') &&
(*pucBuffer != ':') &&
(*pucBuffer != ',') &&
(*pucBuffer != ';') &&
(*pucBuffer != '\t')))
{
bldShowError( "Illegal value in header information");
return( FALSE);
}
if( bHaveParam)
{
switch( uiFieldNum)
{
case 1:
if( uiNum != 0 && !VALID_BLOCK_SIZE( uiNum))
{
bldShowError( "Illegal block size");
return( FALSE);
}
CreateOpts.uiBlockSize = uiNum;
break;
case 4:
if( uiNum > 255)
{
bldShowError( "Illegal application major version");
return( FALSE);
}
CreateOpts.uiAppMajorVer = uiNum;
break;
case 5:
if( uiNum > 255)
{
bldShowError( "Illegal application minor version");
return( FALSE);
}
CreateOpts.uiAppMinorVer = uiNum;
break;
case 6:
CreateOpts.uiMaxRflFileSize = uiNum;
break;
case 7:
CreateOpts.uiDefaultLanguage = uiNum;
break;
case 8:
CreateOpts.uiVersionNum = uiNum;
break;
default:
bldShowError( "Too many parameters in header information");
return( FALSE);
}
}
if( !(*pucBuffer))
{
break;
}
uiFieldNum++;
}
gv_bFixHdrInfo = TRUE;
f_memcpy( &gv_DefaultCreateOpts, &CreateOpts, sizeof( CREATE_OPTS));
return( TRUE);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldOutLabel(
FLMUINT uiCol,
FLMUINT uiRow,
const char * pucLabel,
const char * pucValue,
FLMUINT uiNumValue,
FLMBOOL bLogIt)
{
char szMsg[ 100];
FLMUINT uiLen = (FLMUINT)(VALUE_COLUMN - uiCol - 1);
f_memset( szMsg, '.', uiLen);
szMsg[ uiLen] = 0;
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conStrOutXY( szMsg, uiCol, uiRow);
f_conStrOutXY( pucLabel, uiCol, uiRow);
if( pucValue != NULL)
{
bldOutValue( uiRow, pucValue);
}
else
{
bldOutNumValue( uiRow, uiNumValue);
}
if( (bLogIt) && (gv_bLoggingEnabled))
{
f_strcpy( szMsg, pucLabel);
f_strcpy( &szMsg[ f_strlen( szMsg)], ": ");
if( pucValue != NULL)
{
f_strcpy( &szMsg[ f_strlen( szMsg)], pucValue);
}
else
{
f_sprintf( (char *)(&szMsg[ f_strlen( szMsg)]), "%u",
(unsigned)uiNumValue);
}
bldLogString( szMsg);
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldOutValue(
FLMUINT uiRow,
const char * pucValue)
{
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conStrOutXY( pucValue, VALUE_COLUMN, uiRow);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldOutNumValue(
FLMUINT uiRow,
FLMUINT uiNumber)
{
char szMsg[ 80];
f_sprintf( (char *)szMsg, "%-10u (0x%08X)",
(unsigned)uiNumber, (unsigned)uiNumber);
bldOutValue( uiRow, szMsg);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC RCODE bldGetUserInput(
void
)
{
FLMUINT uiChar;
f_conStrOutXY( "Q,ESC=Quit, Other=Continue: ", 0, 23);
for (;;)
{
if( gv_bShutdown)
{
uiChar = FKB_ESCAPE;
break;
}
else if( f_conHaveKey())
{
uiChar = f_conGetKey();
if( uiChar)
{
break;
}
}
f_yieldCPU();
}
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conClearScreen( 0, 22);
switch( uiChar)
{
case 'q':
case 'Q':
case FKB_ESCAPE:
return( RC_SET( FERR_FAILURE));
default:
break;
}
return( FERR_OK);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldLogStr(
FLMUINT uiIndent,
const char * pucStr)
{
FLMUINT uiLoop;
if( gv_bLoggingEnabled)
{
for( uiLoop = 0; uiLoop < uiIndent; uiLoop++)
{
gv_pucLogBuffer[ gv_uiLogBufferCount++] = ' ';
if( gv_uiLogBufferCount == MAX_LOG_BUFF)
{
bldLogFlush();
}
}
bldLogString( pucStr);
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldLogCorruptError(
CORRUPT_INFO * pCorruptInfo)
{
char szBuf[ 100];
/* Log the container number */
bldLogString( NULL);
bldLogString( "ERROR IN DATABASE");
f_sprintf( (char *)szBuf, "Container Number: %u",
(unsigned)pCorruptInfo->uiErrLfNumber);
bldLogStr( 2, szBuf);
/* Log the block address, if known */
if (pCorruptInfo->uiErrBlkAddress)
{
f_sprintf( (char *)szBuf, "Block Address: 0x%08X (%u)",
(unsigned)pCorruptInfo->uiErrBlkAddress,
(unsigned)pCorruptInfo->uiErrBlkAddress);
bldLogStr( 2, szBuf);
}
/* Log the parent block address, if known */
if (pCorruptInfo->uiErrParentBlkAddress)
{
f_sprintf( (char *)szBuf, "Parent Block Address: 0x%08X (%u)",
(unsigned)pCorruptInfo->uiErrParentBlkAddress,
(unsigned)pCorruptInfo->uiErrParentBlkAddress);
bldLogStr( 2, szBuf);
}
/* Log the element offset, if known */
if (pCorruptInfo->uiErrElmOffset)
{
f_sprintf( (char *)szBuf, "Offset of Element within Block: %u",
(unsigned)pCorruptInfo->uiErrElmOffset);
bldLogStr( 2, szBuf);
}
/* Log the elment record offset, if known */
if (pCorruptInfo->uiErrElmRecOffset != 0xFFFF)
{
f_sprintf( (char *)szBuf, "Offset within Element Record: %u",
(unsigned)pCorruptInfo->uiErrElmRecOffset);
bldLogStr( 2, szBuf);
}
/* Log the record number, if known */
if (pCorruptInfo->uiErrDrn)
{
f_sprintf( (char *)szBuf, "Record Number: %u",
(unsigned)pCorruptInfo->uiErrDrn);
bldLogStr( 2, szBuf);
}
/* Log the field number, if known */
if (pCorruptInfo->uiErrFieldNum)
{
f_sprintf( (char *)szBuf, "Field Number: %u",
(unsigned)pCorruptInfo->uiErrFieldNum);
bldLogStr( 2, szBuf);
}
/* Log the error message */
f_strcpy( szBuf, FlmVerifyErrToStr( pCorruptInfo->eCorruption));
f_sprintf( (char *)(&szBuf [f_strlen( szBuf)]), " (%d)",
(int)pCorruptInfo->eCorruption);
bldLogStr( 2, szBuf);
bldLogStr( 0, NULL);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC RCODE bldProgFunc(
eStatusType eStatus,
void * Parm1,
void * Parm2,
void * pvAppData
)
{
RCODE rc = FERR_OK;
F_UNREFERENCED_PARM( Parm2);
F_UNREFERENCED_PARM( pvAppData);
if( eStatus == FLM_DB_COPY_STATUS)
{
DB_COPY_INFO * pCopyInfo = (DB_COPY_INFO *)Parm1;
char ucDoing [200];
if( gv_ui64DatabaseSize != pCopyInfo->ui64BytesToCopy)
{
gv_ui64DatabaseSize = pCopyInfo->ui64BytesToCopy;
bldOutNumValue( DB_SIZE_ROW, (FLMUINT)gv_ui64DatabaseSize);
}
gv_ui64BytesDone = pCopyInfo->ui64BytesCopied;
bldOutNumValue( BYTES_DONE_ROW, (FLMUINT)gv_ui64BytesDone);
gv_iLastDoing = -1;
if (pCopyInfo->bNewSrcFile)
{
f_sprintf( (char *)ucDoing, "Saving File %-15s",
(char *)pCopyInfo->szSrcFileName);
ucDoing [25] = 0;
bldOutValue( DOING_ROW, ucDoing);
}
}
else if( eStatus == FLM_REBUILD_STATUS)
{
REBUILD_INFO * Progress = (REBUILD_INFO *)Parm1;
/* First update the display */
if( gv_iLastDoing != Progress->iDoingFlag)
{
gv_ui64DatabaseSize = Progress->ui64DatabaseSize;
bldOutNumValue( DB_SIZE_ROW, (FLMUINT)gv_ui64DatabaseSize);
gv_iLastDoing = Progress->iDoingFlag;
if( gv_iLastDoing == REBUILD_GET_BLK_SIZ)
{
bldOutValue( DOING_ROW, "Determining Block Size ");
}
else if( gv_iLastDoing == REBUILD_RECOVER_DICT)
{
bldOutValue( DOING_ROW, "Recovering Dictionaries ");
}
else
{
bldOutValue( DOING_ROW, "Recovering Data ");
}
}
if( gv_iLastDoing == REBUILD_GET_BLK_SIZ)
{
if( gv_ui64DatabaseSize != Progress->ui64DatabaseSize)
{
gv_ui64DatabaseSize = Progress->ui64DatabaseSize;
bldOutNumValue( DB_SIZE_ROW, (FLMUINT)gv_ui64DatabaseSize);
}
gv_ui64BytesDone = Progress->ui64BytesExamined;
bldOutNumValue( BYTES_DONE_ROW, (FLMUINT)gv_ui64BytesDone);
}
else
{
if( gv_ui64DatabaseSize != Progress->ui64DatabaseSize)
{
gv_ui64DatabaseSize = Progress->ui64DatabaseSize;
bldOutNumValue( DB_SIZE_ROW, (FLMUINT)gv_ui64DatabaseSize);
}
gv_ui64BytesDone = Progress->ui64BytesExamined;
bldOutNumValue( BYTES_DONE_ROW, (FLMUINT)gv_ui64BytesDone);
if( gv_uiTotalRecs != Progress->uiTotRecs)
{
gv_uiTotalRecs = Progress->uiTotRecs;
bldOutNumValue( TOTAL_REC_ROW, gv_uiTotalRecs);
}
if( gv_iLastDoing == REBUILD_RECOVER_DICT)
{
if( gv_uiDictRecsRecovered != Progress->uiRecsRecov)
{
gv_uiDictRecsRecovered = Progress->uiRecsRecov;
bldOutNumValue( DICT_RECOV_ROW, gv_uiDictRecsRecovered);
}
}
else
{
if( gv_uiRecsRecovered != Progress->uiRecsRecov)
{
gv_uiRecsRecovered = Progress->uiRecsRecov;
bldOutNumValue( RECOV_ROW, gv_uiRecsRecovered);
}
}
}
}
else if( eStatus == FLM_PROBLEM_STATUS)
{
CORRUPT_INFO * pCorruptInfo = (CORRUPT_INFO *)Parm1;
bldLogCorruptError( pCorruptInfo);
goto Exit;
}
else if( eStatus == FLM_CHECK_RECORD_STATUS)
{
CHK_RECORD * pChkRec = (CHK_RECORD *)Parm1;
if (pChkRec->pDictRecSet)
{
pChkRec->pDictRecSet->clear();
}
}
if ((f_conHaveKey()) && (f_conGetKey() == FKB_ESCAPE))
{
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conClearScreen( 0, 22);
f_conSetBackFore (FLM_RED, FLM_WHITE);
f_conStrOutXY( "ESCAPE key pressed", 0, 22);
rc = bldGetUserInput();
goto Exit;
}
f_yieldCPU();
Exit:
return( rc);
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldShowError(
const char * Message)
{
if( !gv_bBatchMode)
{
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conClearScreen( 0, 22);
f_conSetBackFore( FLM_RED, FLM_WHITE);
f_conStrOutXY( Message, 0, 22);
f_conStrOutXY( "Press any character to continue, ESCAPE to quit: ", 0, 23);
for (;;)
{
if (gv_bShutdown)
{
break;
}
else if (f_conHaveKey())
{
if (f_conGetKey() == FKB_ESCAPE)
{
gv_bShutdown = TRUE;
}
break;
}
f_yieldCPU();
}
f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
f_conClearScreen( 0, 22);
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldLogFlush(
void
)
{
FLMUINT uiBytesWritten;
if( gv_uiLogBufferCount)
{
gv_pLogFile->write( FLM_IO_CURRENT_POS,
gv_uiLogBufferCount, gv_pucLogBuffer, &uiBytesWritten);
gv_uiLogBufferCount = 0;
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldLogString(
const char * pucStr)
{
FLMUINT uiLen;
FLMUINT uiLoop;
if( (gv_bLoggingEnabled) && (gv_pucLogBuffer != NULL))
{
uiLen = (FLMUINT)((pucStr != NULL) ? (FLMUINT)f_strlen( pucStr) : 0);
for( uiLoop = 0; uiLoop < uiLen; uiLoop++)
{
gv_pucLogBuffer[ gv_uiLogBufferCount++] = *pucStr++;
if( gv_uiLogBufferCount == MAX_LOG_BUFF)
{
bldLogFlush();
}
}
gv_pucLogBuffer[ gv_uiLogBufferCount++] = '\r';
if( gv_uiLogBufferCount == MAX_LOG_BUFF)
{
bldLogFlush();
}
gv_pucLogBuffer[ gv_uiLogBufferCount++] = '\n';
if( gv_uiLogBufferCount == MAX_LOG_BUFF)
{
bldLogFlush();
}
}
}
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC RCODE bldGetCreateOpts(
const char * pszFileName,
CREATE_OPTS * pCreateOpts)
{
RCODE rc = FERR_OK;
char szBuf[ 80];
FLMBYTE ucLogHdr [LOG_HEADER_SIZE];
HDR_INFO HdrInfo;
FLMUINT uiVersion;
IF_FileHdl * pCFileHdl = NULL;
f_memset( pCreateOpts, 0, sizeof( CREATE_OPTS));
if( gv_bFixHdrInfo)
{
f_memcpy( pCreateOpts, &gv_DefaultCreateOpts, sizeof( CREATE_OPTS));
goto Exit;
}
if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszFileName,
FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &pCFileHdl)))
{
goto Exit;
}
if( (rc = flmGetHdrInfo( pCFileHdl, &HdrInfo.FileHdr,
&HdrInfo.LogHdr, ucLogHdr)) == FERR_NOT_FLAIM)
{
uiVersion = gv_DefaultCreateOpts.uiVersionNum;
f_memcpy( pCreateOpts, &gv_DefaultCreateOpts, sizeof( CREATE_OPTS));
rc = FERR_OK;
}
else
{
uiVersion = HdrInfo.FileHdr.uiVersionNum;
flmGetCreateOpts( &HdrInfo.FileHdr, ucLogHdr, pCreateOpts);
}
if (rc != FERR_OK &&
rc != FERR_INCOMPLETE_LOG &&
rc != FERR_BLOCK_CHECKSUM)
{
if (((rc == FERR_UNSUPPORTED_VERSION) || (rc == FERR_NEWER_FLAIM)) &&
(uiVersion == 999))
{
rc = FERR_OK;
}
else
{
f_strcpy( szBuf, "Error reading header info from ");
f_strcpy( &szBuf[ f_strlen( szBuf)], pszFileName);
f_strcpy( &szBuf[ f_strlen( szBuf)], ": ");
f_strcpy( &szBuf[ f_strlen( szBuf)], FlmErrorString( rc));
bldShowError( szBuf);
if( gv_bLoggingEnabled)
{
bldLogString( szBuf);
}
goto Exit;
}
}
else
{
rc = FERR_OK;
}
Exit:
if( pCFileHdl)
{
pCFileHdl->Release();
}
return( rc);
}