예제 #1
0
/*******************************************************************************
Desc:	Renames a database
*******************************************************************************/
FLMEXP RCODE FLMAPI FlmDbRename(
	const char *		pszDbName,
	const char *		pszDataDir,
	const char *		pszRflDir,
	const char *		pszNewDbName,
	FLMBOOL				bOverwriteDestOk,
	STATUS_HOOK			fnStatusCallback,
	void *				UserData)
{
	RCODE					rc = FERR_OK;
	IF_FileHdl *		pFileHdl = NULL;
	FLMUINT				uiFileNumber;
	FILE_HDR				FileHdr;
	LOG_HDR				LogHdr;
	DBRenameInfo *		pRenameList = NULL;
	FLMBOOL				bFileFound;
	FLMBYTE *			pucBuffer = NULL;
	FLMBYTE *			pucLogHdr;
	char *				pszOldName;
	char *				pszNewName;
	char *				pszOldDataName;
	char *				pszNewDataName;
	char *				pszFullNewName;
	char					szOldBase[ F_FILENAME_SIZE];
	char					szNewBase[ F_FILENAME_SIZE];
	char *				pszExtOld;
	char *				pszExtNew;
	char *				pszDataExtOld;
	char *				pszDataExtNew;

	// Cannot handle empty database name.

	flmAssert( pszDbName && *pszDbName);
	flmAssert( pszNewDbName && *pszNewDbName);

	// Allocate memory for a read buffer, the log header, and various
	// file names.

	if( RC_BAD( rc = f_allocAlignedBuffer( 
		2048 + LOG_HEADER_SIZE + F_PATH_MAX_SIZE * 5, &pucBuffer)))
	{
		goto Exit;
	}
	pucLogHdr = pucBuffer + 2048;
	pszOldName = (char *)(pucLogHdr + LOG_HEADER_SIZE);
	pszNewName = pszOldName + F_PATH_MAX_SIZE;
	pszOldDataName = pszNewName + F_PATH_MAX_SIZE;
	pszNewDataName = pszOldDataName + F_PATH_MAX_SIZE;
	pszFullNewName = pszNewDataName + F_PATH_MAX_SIZE;

	// There must be either no directory specified for the new name, or
	// it must be identical to the old directory.

	if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathReduce( 
		pszDbName, pszOldName, szOldBase)))
	{
		goto Exit;
	}
	
	if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathReduce( 
		pszNewDbName, pszNewName, szNewBase)))
	{
		goto Exit;
	}

	// Directories must be the same.

	if (*pszNewName && f_stricmp( pszOldName, pszNewName) != 0)
	{
		rc = RC_SET( FERR_INVALID_PARM);
		goto Exit;
	}
	
	f_strcpy( pszNewName, pszOldName);
	
	if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( 
		pszNewName, szNewBase)))
	{
		goto Exit;
	}

	f_strcpy( pszFullNewName, pszNewName);
	f_strcpy( pszOldName, pszDbName);

	if( pszDataDir && *pszDataDir)
	{
		f_strcpy( pszOldDataName, pszDataDir);
		f_strcpy( pszNewDataName, pszDataDir);
		
		if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( 
			pszOldDataName, szOldBase)))
		{
			goto Exit;
		}
		
		if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( 
			pszNewDataName, szNewBase)))
		{
			goto Exit;
		}
	}
	else
	{
		f_strcpy( pszNewDataName, pszNewName);
		f_strcpy( pszOldDataName, pszOldName);
	}

	// First make sure we have closed the databases and gotten rid of
	// them from our internal memory tables - in case they had been open.

	if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, 
		(void *)pszDbName, (void *)pszDataDir)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, 
		(void *)pszFullNewName, (void *)pszDataDir)))
	{
		goto Exit;
	}
	
	gv_FlmSysData.pFileHdlCache->closeUnusedFiles();

	// Open the file so we can get the log header.

	if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszDbName, 
		gv_FlmSysData.uiFileOpenFlags, &pFileHdl)))
	{
		goto Exit;
	}

	// Read the header to get the low and high RFL log
	// file numbers.

	if (RC_BAD( flmReadAndVerifyHdrInfo( NULL, pFileHdl,
								pucBuffer, &FileHdr, &LogHdr, pucLogHdr)))
	{
		goto Exit;
	}

	// Close the file.

	pFileHdl->Release();
	pFileHdl = NULL;

	// Start renaming files, beginning with the main DB file.

	if( RC_BAD( rc = flmRenameFile( pszDbName, pszFullNewName,
								bOverwriteDestOk, FALSE,
								&pRenameList, &bFileFound,
								fnStatusCallback, UserData)))
	{
		goto Exit;
	}

	// Find where the extension of the old and new database names are

	pszExtOld = pszOldName + f_strlen( pszOldName) - 1;
	pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName) - 1;
	while (pszExtOld != pszOldName && *pszExtOld != '.')
	{
		pszExtOld--;

		// Both the old db name and old data name have the same
		// base name, so we can decrement pszDataExtOld
		// at the same time we decrement pszExtOld.

		pszDataExtOld--;
	}
	
	if (*pszExtOld != '.')
	{
		pszExtOld = pszOldName + f_strlen( pszOldName);
		pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName);
	}

	pszExtNew = pszNewName + f_strlen( pszNewName) - 1;
	pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName) - 1;
	
	while (pszExtNew != pszOldName && *pszExtNew != '.')
	{
		pszExtNew--;

		// Both the new db name and new data name have the same
		// base name, so we can decrement pszDataExtNew
		// at the same time we decrement pszExtNew.

		pszDataExtNew--;
	}
	
	if (*pszExtNew != '.')
	{
		pszExtNew = pszNewName + f_strlen( pszNewName);
		pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName);
	}

	// Rename the .lck file, if any.  This is necessary for UNIX.

	f_strcpy( pszExtOld, ".lck");
	f_strcpy( pszExtNew, ".lck");
	if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName,
								bOverwriteDestOk, TRUE,
								&pRenameList, &bFileFound,
								fnStatusCallback, UserData)))
	{
		goto Exit;
	}

	// Rename block (data) files.

	uiFileNumber = 1;
	for (;;)
	{
		F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum,
			uiFileNumber, pszDataExtOld);
		F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum,
			uiFileNumber, pszDataExtNew);

		if (RC_BAD( rc = flmRenameFile( pszOldDataName, pszNewDataName,
									bOverwriteDestOk, TRUE,
									&pRenameList, &bFileFound,
									fnStatusCallback, UserData)))
		{
			goto Exit;
		}
		if (!bFileFound)
		{
			break;
		}
		if (uiFileNumber ==
				MAX_DATA_BLOCK_FILE_NUMBER( FileHdr.uiVersionNum))
		{
			break;
		}
		uiFileNumber++;
	}

	// Rename rollback log files.

	uiFileNumber =
			FIRST_LOG_BLOCK_FILE_NUMBER (FileHdr.uiVersionNum);
	for (;;)
	{
		F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum,
			uiFileNumber, pszExtOld);
		F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum,
			uiFileNumber, pszExtNew);

		if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName,
									bOverwriteDestOk, TRUE,
									&pRenameList, &bFileFound,
									fnStatusCallback, UserData)))
		{
			goto Exit;
		}
		
		if (!bFileFound)
		{
			break;
		}
		
		if (uiFileNumber ==
				MAX_LOG_BLOCK_FILE_NUMBER( FileHdr.uiVersionNum))
		{
			break;
		}
		
		uiFileNumber++;
	}

	// Rename roll-forward log files.

	if (FileHdr.uiVersionNum < FLM_FILE_FORMAT_VER_4_3)
	{

		// For pre-4.3 versions, only need to rename one RFL file.

		if (RC_BAD( rc = rflGetFileName( FileHdr.uiVersionNum,
									pszDbName, pszRflDir, 1, pszOldName)))
		{
			goto Exit;
		}
		if (RC_BAD( rc = rflGetFileName( FileHdr.uiVersionNum,
									pszFullNewName, pszRflDir, 1, pszNewName)))
		{
			goto Exit;
		}
		if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName,
									bOverwriteDestOk, TRUE,
									&pRenameList, &bFileFound,
									fnStatusCallback, UserData)))
		{
			goto Exit;
		}
	}
	else
	{

		// For 4.3 and greater, rename the RFL directory.

		if (RC_BAD( rc = rflGetDirAndPrefix( FileHdr.uiVersionNum,
									pszDbName, pszRflDir, pszOldName, szOldBase)))
		{
			goto Exit;
		}

		if (RC_BAD( rc = rflGetDirAndPrefix( FileHdr.uiVersionNum,
									pszFullNewName, pszRflDir, pszNewName,
									szNewBase)))
		{
			goto Exit;
		}

		if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName,
									bOverwriteDestOk, TRUE,
									&pRenameList, &bFileFound,
									fnStatusCallback, UserData)))
		{
			goto Exit;
		}
	}

Exit:

	if( pFileHdl)
	{
		pFileHdl->Release();
	}
	
	if( pucBuffer)
	{
		f_freeAlignedBuffer( &pucBuffer);
	}

	// Free the list of renamed files.

	while( pRenameList)
	{
		DBRenameInfo *		pRenameFile;

		pRenameFile = pRenameList;
		pRenameList = pRenameList->pNext;

		// If we had an error of some sort, attempt to un-rename
		// the file that had been renamed.

		if (RC_BAD( rc))
		{
			gv_FlmSysData.pFileSystem->renameFile( 
				pRenameFile->Info.szDstFileName, pRenameFile->Info.szSrcFileName);
		}
		
		f_free( &pRenameFile);
	}
	
	return( rc);
}
예제 #2
0
/********************************************************************
Desc: Loads the database with objects.
*********************************************************************/
RCODE gigaLoadDatabase( void)
{
	RCODE				rc = NE_FLM_OK;
	FLMBOOL			bTransActive = FALSE;
	FLMBOOL			bCommitTrans = FALSE;
	FLMUINT			uiObjsInTrans = 0;
	FLMUINT			uiChar = 0;
	FLMUINT			bSuspend = FALSE;
	FlmRecord *		pNewRec = NULL;

	// Set cache size, if specified on command line.

	if( gv_uiCacheSize)
	{
		if( RC_BAD( rc = FlmSetHardMemoryLimit( 0, FALSE, 0,
			gv_uiCacheSize, 0)))
		{
			gigaOutputRcErr( "setting cache size", rc);
			goto Exit;
		}
	}

	// Set block cache percentage, if it is not default.
	
	if( gv_uiBlockCachePercentage != 50)
	{
		if( RC_BAD( rc = FlmConfig( FLM_BLOCK_CACHE_PERCENTAGE,
			(void *)gv_uiBlockCachePercentage, (void *)0)))
		{
			gigaOutputRcErr( "setting block cache percentage", rc);
			goto Exit;
		}
	}

	// Set the maximum and low dirty cache, if one was specified

	if( gv_uiMaxDirtyCache)
	{
		if( RC_BAD( rc = FlmConfig( FLM_MAX_DIRTY_CACHE,
			(void *)gv_uiMaxDirtyCache, (void *)gv_uiLowDirtyCache)))
		{
			gigaOutputRcErr( "setting maximum dirty cache", rc);
			goto Exit;
		}
	}

	// Set checkpoint interval, if one is specified.

	if( gv_uiCPInterval != 0xFFFFFFFF)
	{
		if( RC_BAD( rc = FlmConfig( FLM_MAX_CP_INTERVAL, 
			(void *)gv_uiCPInterval, (void *)0)))
		{
			gigaOutputRcErr( "setting checkpoint interval", rc);
			goto Exit;
		}
	}
	
	// Enable/Disable direct I/O
	
	if( RC_BAD( rc = FlmConfig( FLM_DIRECT_IO_STATE, 
		(void *)!gv_bDisableDirectIO, NULL)))
	{
		goto Exit;
	}

	// Create the database.
	
	(void)FlmDbRemove( gv_szDibName, gv_szDataDir, gv_szRflDir, TRUE);
	
	if( RC_BAD( rc = FlmDbCreate( gv_szDibName, gv_szDataDir, gv_szRflDir, 
		NULL, gv_pszGigaDictionary, NULL, &gv_hDb)))
	{
		gigaOutputRcErr( "creating database", rc);
		goto Exit;
	}
	
	if( RC_BAD( rc = FlmDbConfig( gv_hDb, 
		FDB_RFL_FOOTPRINT_SIZE, (void *)(512 * 1024 * 1024), NULL)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = FlmDbConfig( gv_hDb, 
		FDB_RBL_FOOTPRINT_SIZE, (void *)(512 * 1024 * 1024), NULL)))
	{
		goto Exit;
	}

	// Create the display

	gv_uiTotalLoaded = 0;
	gv_ui10SecTotal = 0;
	
	f_mutexLock( gv_hWindowMutex);
	FTXWinClear( gv_pWindow);
	f_mutexUnlock( gv_hWindowMutex);

	gigaOutputLabel( MAX_CACHE_ROW, "Maximum Cache Size (bytes)");
	gigaOutputLabel( USED_CACHE_ROW, "Cache Used (bytes)");
	gigaOutputLabel( ITEMS_CACHED_ROW, "Cache Used (items)");
	gigaOutputLabel( DIRTY_CACHE_ROW, "Dirty Cache (bytes)");
	gigaOutputLabel( LOG_CACHE_ROW, "Log Cache (bytes)");
	gigaOutputLabel( FREE_CACHE_ROW, "Free Cache (bytes)");
	gigaOutputLabel( CP_STATE_ROW, "Checkpoint State");
	
	gigaUpdateMemInfo();

	gigaOutputLabel( DB_NAME_ROW, "Database Name");
	gigaOutputStr( DB_NAME_ROW, gv_szDibName);

	gigaOutputLabel( TOTAL_TO_LOAD_ROW, "Total To Load");
	gigaOutputUINT( TOTAL_TO_LOAD_ROW, gv_uiTotalToLoad);

	gigaOutputLabel( TRANS_SIZE_ROW, "Transaction Size");
	gigaOutputUINT( TRANS_SIZE_ROW, gv_uiTransSize);

	gigaOutputLabel( TOTAL_LOADED_ROW, "Total Loaded");
	gigaOutputUINT( TOTAL_LOADED_ROW, gv_uiTotalLoaded);

	gigaOutputLabel( ADDS_PER_SEC_CURRENT, "Adds/Sec. (10 secs)");
	gigaOutputUINT( ADDS_PER_SEC_CURRENT, 0);

	gigaOutputLabel( ADDS_PER_SEC_OVERALL, "Adds/Sec. (overall)");
	gigaOutputUINT( ADDS_PER_SEC_OVERALL, 0);

	gigaOutputLabel( ELAPSED_TIME_ROW, "Elapsed Time");
	gigaOutputStr( ELAPSED_TIME_ROW, "<none>");

	if( RC_BAD( rc = gigaStartScreenThread()))
	{
		goto Exit;
	}
	
	gv_ui10SecStartTime = gv_uiStartTime = FLM_GET_TIMER();
	gv_ui10Secs = FLM_SECS_TO_TIMER_UNITS( 10);
	gv_ui1Sec = FLM_SECS_TO_TIMER_UNITS( 1);
	
	for( ;;)
	{
		// See if we have been told to shut down, or if the user 
		// has pressed escape.

		if( gv_bShutdown)
		{
			break;
		}

		// Every 127 objects, see if character was pressed and update 
		// count on screen.

		if( (gv_uiTotalLoaded & 0x7F) == 0)
		{
			f_yieldCPU();
			
			if( (uiChar = gigaSeeIfQuit()) != 0)
			{
				if( uiChar == FKB_ESCAPE)
				{
					break;
				}
				else if( uiChar == 's' || uiChar == 'S')
				{
					bSuspend = TRUE;
				}
			}

			// Check for other keyboard options
		}
		else if( (gv_uiTotalLoaded & 0x7) == 0)
		{
			FLMUINT		uiElapsedTime;
			FLMUINT		uiCurrTime;

			uiCurrTime = FLM_GET_TIMER();

			// If at least 10 seconds have elapsed, redisplay the average
			// rate values.

			if( (uiElapsedTime = FLM_ELAPSED_TIME( uiCurrTime,
				gv_ui10SecStartTime)) >= gv_ui10Secs)
			{
				gigaUpdateLoadTimes();
			}
		}

		// Start a transaction, if one is not going.

		if( !bTransActive)
		{
			if( bSuspend)
			{
				uiChar = gigaGetInput(
					"Load suspended, press any character to continue loading: ",
					NULL);
				bSuspend = FALSE;
			}
			
			if( RC_BAD( rc = gigaStartTrans()))
			{
				goto Exit;
			}
			
			bTransActive = TRUE;
			bCommitTrans = FALSE;
			uiObjsInTrans = 0;
		}

		// Increment the load counters and determine if this will be the
		// last object of the transaction.

		gv_uiTotalLoaded++;
		uiObjsInTrans++;
		
		if( uiObjsInTrans == gv_uiTransSize ||
			 gv_uiTotalLoaded == gv_uiTotalToLoad)
		{
			bCommitTrans = TRUE;
		}

		// Create a new object.

		if( RC_BAD( rc = gigaMakeNewRecord( &pNewRec)))
		{
			goto Exit;
		}
		
		if( RC_BAD( rc = FlmRecordAdd( gv_hDb, FLM_DATA_CONTAINER, 
			NULL, pNewRec, FLM_DONT_INSERT_IN_CACHE)))
		{
			goto Exit;
		}
		
		// Commit when we reach the transaction size or the total to load.
		// NOTE: The bCommitTrans flag is set above.

		if( bCommitTrans)
		{
			if( RC_BAD( rc = gigaCommitTrans()))
			{
				goto Exit;
			}
			
			bTransActive = FALSE;
		}

		// See if we are done.

		if( gv_uiTotalLoaded == gv_uiTotalToLoad)
		{
			flmAssert( !bTransActive);
			break;
		}
	}

Exit:

	if( pNewRec)
	{
		pNewRec->Release();
	}

	if( bTransActive)
	{
		(void)FlmDbTransAbort( gv_hDb);
	}
	
	if( gv_hDb != HFDB_NULL)
	{
		FlmDbCheckpoint( gv_hDb, FLM_NO_TIMEOUT);
		gigaStopScreenThread();
		FlmDbClose( &gv_hDb);

		// This will cause us to wait for the last checkpoint
		// to finish.

		(void)FlmConfig( FLM_CLOSE_FILE, (void *)gv_szDibName,
								(void *)gv_szDataDir);
	}
	
	gigaUpdateLoadTimes();
	gigaStopScreenThread();
	f_threadDestroy( &gv_pIxManagerThrd);
	
	return( rc);
}
예제 #3
0
파일: fdbcopy.cpp 프로젝트: ajumi2/libflaim
/*******************************************************************************
Desc:	Copies a database, including roll-forward log files.
*******************************************************************************/
FLMEXP RCODE FLMAPI FlmDbCopy(
	const char *		pszSrcDbName,
	const char *		pszSrcDataDir,
	const char *		pszSrcRflDir,
	const char *		pszDestDbName,
	const char *		pszDestDataDir,
	const char *		pszDestRflDir,
	STATUS_HOOK			fnStatusCallback,
	void *				UserData)
{
	RCODE				rc = FERR_OK;
	FLMBYTE *		pucLastCommittedLogHdr;
	HFDB				hDb = HFDB_NULL;
	FDB *				pDb;
	FLMBOOL			bDbLocked = FALSE;
	FLMUINT			uiDbVersion;

	// Make sure the destination database is closed

	if (RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE,
		(void *)pszDestDbName, (void *)pszDestDataDir)))
	{
		goto Exit;
	}
	
	gv_FlmSysData.pFileHdlCache->closeUnusedFiles();	

	// Open the database so we can force a checkpoint.

	if (RC_BAD( rc = FlmDbOpen( pszSrcDbName, pszSrcDataDir, pszSrcRflDir,
								0, NULL, &hDb)))
	{
		goto Exit;
	}
	pDb = (FDB *)hDb;

	// Need to lock the database, because we want to do a checkpoint
	// and then the copy immediately after without letting other
	// threads have the opportunity to get in and update the
	// database.

	if (RC_BAD( rc = FlmDbLock( hDb, FLM_LOCK_EXCLUSIVE, 0, FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}
	bDbLocked = TRUE;

	// Force a checkpoint

	if (RC_BAD( rc = FlmDbCheckpoint( hDb, FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}

	pucLastCommittedLogHdr = &pDb->pFile->ucLastCommittedLogHdr[ 0];

	// Get the low and high RFL log file numbers from the log
	// header.

	uiDbVersion = pDb->pFile->FileHdr.uiVersionNum;

	// Once we get this far, we have exclusive access to the database
	// and we have forced a checkpoint.  The database's contents are
	// guaranteed to be on disk at this point, and they will not
	// change.

	rc = flmCopyDb( uiDbVersion, pszSrcDbName, pszSrcDataDir, pszSrcRflDir,
						pszDestDbName, pszDestDataDir, pszDestRflDir,
						fnStatusCallback, UserData);

Exit:

	// Unlock and close the database

	if (bDbLocked)
	{
		FlmDbUnlock( hDb);
	}

	if (hDb != HFDB_NULL)
	{
		(void)FlmDbClose( &hDb);
		(void)FlmConfig( FLM_CLOSE_FILE, (void *)pszSrcDbName,
								(void *)pszSrcDataDir);
	}
	return( rc);
}
예제 #4
0
파일: rebuild.cpp 프로젝트: ajumi2/libflaim
/********************************************************************
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);
}