/*************************************************************************** Desc: This routine reads through the blocks in the AVAIL list and verifies that we don't have a loop or some other corruption in the list. *****************************************************************************/ RCODE F_DbCheck::verifyAvailList( FLMBOOL * pbStartOverRV) { RCODE rc = NE_XFLM_OK; m_Progress.ui32LfNumber = 0; m_Progress.ui32LfType = 0; m_Progress.i32CheckPhase = XFLM_CHECK_AVAIL_BLOCKS; m_Progress.bStartFlag = TRUE; if (RC_BAD( rc = chkCallProgFunc())) { goto Exit; } m_Progress.bStartFlag = FALSE; f_yieldCPU(); if (RC_BAD( rc = verifyBlkChain( &m_pDbInfo->m_AvailBlocks, XFLM_LOCALE_AVAIL_LIST, m_pDb->m_uiFirstAvailBlkAddr, BT_FREE, pbStartOverRV)) || *pbStartOverRV) { goto Exit; } 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: This routine verifies the LFH blocks. *****************************************************************************/ RCODE F_DbCheck::verifyLFHBlocks( FLMBOOL * pbStartOverRV) { RCODE rc = NE_XFLM_OK; m_Progress.ui32LfNumber = 0; m_Progress.ui32LfType = 0; m_Progress.i32CheckPhase = XFLM_CHECK_LFH_BLOCKS; m_Progress.bStartFlag = TRUE; if (RC_BAD( rc = chkCallProgFunc())) { goto Exit; } m_Progress.bStartFlag = FALSE; f_yieldCPU(); // Go through the LFH blocks. if (RC_BAD( rc = verifyBlkChain( &m_pDbInfo->m_LFHBlocks, XFLM_LOCALE_LFH_LIST, (FLMUINT)m_pDb->m_pDatabase->m_lastCommittedDbHdr.ui32FirstLFBlkAddr, BT_LFH_BLK, pbStartOverRV)) || *pbStartOverRV) { goto Exit; } Exit: return( rc); }
/**************************************************************************** Desc: This routine shuts down all threads in the NLM. ****************************************************************************/ void gigaCleanup( void) { gv_bShutdown = TRUE; while( gv_bRunning) { f_yieldCPU(); } }
/**************************************************************************** Desc: This routine shuts down all threads in the NLM. ****************************************************************************/ FSTATIC void utilCleanup( void ) { gv_bShutdown = TRUE; while( gv_bRunning) { f_yieldCPU(); } }
/**************************************************************************** Name: refresh Desc: *****************************************************************************/ void F_DynamicList::refresh( void) { DLIST_NODE * pTmp; FLMUINT uiLoop; FTX_SCREEN * pScreen = NULL; if( !m_bChanged) { return; } if( RC_BAD( FTXWinGetScreen( m_pListWin, &pScreen))) { flmAssert( 0); goto Exit; } FTXSetRefreshState( TRUE); pTmp = m_pCur; uiLoop = m_uiRow; while( pTmp && uiLoop > 0) { pTmp = pTmp->pPrev; uiLoop--; } if( !pTmp) { pTmp = m_pFirst; } uiLoop = 0; while( pTmp && uiLoop < m_uiListRows) { pTmp->pDispHook( m_pListWin, (FLMBOOL)(pTmp == m_pCur ? TRUE : FALSE), uiLoop, pTmp->uiKey, pTmp->pvData, pTmp->uiDataLen, this); pTmp = pTmp->pNext; uiLoop++; f_yieldCPU(); } if( uiLoop < m_uiListRows) { FTXWinClearXY( m_pListWin, 0, uiLoop); } FTXSetRefreshState( FALSE); m_bChanged = FALSE; Exit: ; }
/******************************************************************** 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: Starts a transaction and does a few modifications that are necessary at the beginning of a transaction. *********************************************************************/ RCODE gigaStartTrans( void) { RCODE rc = NE_FLM_OK; FLMUINT uiChar; while( !gv_bShutdown) { if( RC_BAD( rc = FlmDbTransBegin( gv_hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) { if( rc != FERR_MUST_WAIT_CHECKPOINT) { gigaOutputRcErr( "starting transaction", rc); goto Exit; } f_yieldCPU(); if( (uiChar = gigaSeeIfQuit()) != 0) { if (uiChar == FKB_ESCAPE) { gigaOutputRcErr( "starting transaction", rc); goto Exit; } } } else { break; } } Exit: return( rc); }
/******************************************************************** Desc: This routine follows all of the blocks in a chain, verifying that they are properly linked. It also verifies each block's header. *********************************************************************/ RCODE F_DbCheck::verifyBlkChain( BLOCK_INFO * pBlkInfo, FLMUINT uiLocale, FLMUINT uiFirstBlkAddr, FLMUINT uiBlkType, FLMBOOL * pbStartOverRV ) { RCODE rc = NE_XFLM_OK; FLMINT32 i32VerifyCode = 0; F_CachedBlock * pSCache = NULL; F_BLK_HDR * pBlkHdr = NULL; FLMUINT uiPrevBlkAddress; FLMUINT uiBlkCount = 0; STATE_INFO StateInfo; FLMBOOL bStateInitialized = FALSE; FLMUINT64 ui64SaveBytesExamined; FLMUINT uiBlockSize = m_pDb->m_pDatabase->getBlockSize(); FLMUINT uiMaxBlocks = (FLMUINT)(FSGetSizeInBytes( m_pDb->m_pDatabase->getMaxFileSize(), m_pDb->m_uiLogicalEOF) / (FLMUINT64)uiBlockSize); uiPrevBlkAddress = 0; /* There must be at least ONE block if it is the LFH chain. */ if ((uiBlkType == BT_LFH_BLK) && (uiFirstBlkAddr == 0)) { i32VerifyCode = FLM_BAD_LFH_LIST_PTR; (void)chkReportError( i32VerifyCode, (FLMUINT32)uiLocale, 0, 0, 0xFF, 0, 0, 0, 0); goto Exit; } /* Read through all of the blocks, verifying them as we go. */ Restart_Chain: uiBlkCount = 0; flmInitReadState( &StateInfo, &bStateInitialized, (FLMUINT)m_pDb->m_pDatabase-> m_lastCommittedDbHdr.ui32DbVersion, m_pDb, NULL, (FLMUINT)((uiBlkType == BT_FREE) ? (FLMUINT)0xFF : (FLMUINT)0), uiBlkType, NULL); ui64SaveBytesExamined = m_Progress.ui64BytesExamined; StateInfo.ui32BlkAddress = (FLMUINT32)uiFirstBlkAddr; while ((StateInfo.ui32BlkAddress != 0) && (uiBlkCount < uiMaxBlocks)) { StateInfo.pBlkHdr = NULL; if( RC_BAD( rc = blkRead( StateInfo.ui32BlkAddress, &pBlkHdr, &pSCache, &i32VerifyCode))) { if (rc == NE_XFLM_OLD_VIEW) { FLMUINT uiSaveDictSeq = m_pDb->m_pDict->getDictSeq(); if (RC_BAD( rc = getDictInfo())) goto Exit; // If the dictionary ID changed, start over. if (m_pDb->m_pDict->getDictSeq() != uiSaveDictSeq) { *pbStartOverRV = TRUE; goto Exit; } m_Progress.ui64BytesExamined = ui64SaveBytesExamined; goto Restart_Chain; } pBlkInfo->i32ErrCode = i32VerifyCode; pBlkInfo->uiNumErrors++; rc = chkReportError( i32VerifyCode, (FLMUINT32)uiLocale, 0, 0, 0xFF, StateInfo.ui32BlkAddress, 0, 0, 0); } StateInfo.pBlkHdr = pBlkHdr; uiBlkCount++; m_Progress.ui64BytesExamined += (FLMUINT64)uiBlockSize; if (RC_BAD( rc = chkCallProgFunc())) { goto Exit; } f_yieldCPU(); if ((i32VerifyCode = flmVerifyBlockHeader( &StateInfo, pBlkInfo, uiBlockSize, 0xFFFFFFFF, uiPrevBlkAddress, TRUE)) != 0) { pBlkInfo->i32ErrCode = i32VerifyCode; pBlkInfo->uiNumErrors++; chkReportError( i32VerifyCode, (FLMUINT32)uiLocale, 0, 0, 0xFF, StateInfo.ui32BlkAddress, 0, 0, 0); goto Exit; } uiPrevBlkAddress = StateInfo.ui32BlkAddress; StateInfo.ui32BlkAddress = pBlkHdr->ui32NextBlkInChain; } if (StateInfo.ui32BlkAddress != 0 && RC_OK( m_LastStatusRc)) { switch (uiBlkType) { case BT_LFH_BLK: i32VerifyCode = FLM_BAD_LFH_LIST_END; break; case BT_FREE: i32VerifyCode = FLM_BAD_AVAIL_LIST_END; break; } pBlkInfo->i32ErrCode = i32VerifyCode; pBlkInfo->uiNumErrors++; chkReportError( i32VerifyCode, (FLMUINT32)uiLocale, 0, 0, 0xFF, (FLMUINT32)uiPrevBlkAddress, 0, 0, 0); goto Exit; } Exit: if( pSCache) { ScaReleaseCache( pSCache, FALSE); } else if( pBlkHdr) { f_free( &pBlkHdr); } if (RC_OK(rc) && (i32VerifyCode != 0)) { rc = RC_SET( NE_XFLM_DATA_ERROR); } return( rc); }
/******************************************************************** 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); }
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 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); }