//------------------------------------------------------------------------- // Desc: Utility routines for presenting selection and statistics lists. // Tabs: 3 // // Copyright (c) 2000-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: flm_lutl.cpp 12334 2006-01-23 12:45:35 -0700 (Mon, 23 Jan 2006) dsanders $ //------------------------------------------------------------------------- #include "flm_lutl.h" extern FLMBOOL gv_bShutdown; FSTATIC RCODE ixDisplayHook( FTX_WINDOW * pWin, FLMBOOL bSelected, FLMUINT uiRow, FLMUINT uiKey, void * pvData, FLMUINT uiDataLen, F_DynamicList* pDynamicList); FSTATIC void flstIndexUpdateEventHook( FEventType eEventType, void * pvAppData, void * pvEventData1, void * pvEventData2); #define MAX_VALS_TO_SAVE 10 typedef struct IxDisplayInfo { char szName [20]; FINDEX_STATUS IndexStatus; FLMUINT uiSaveRecsProcessed [MAX_VALS_TO_SAVE]; FLMUINT uiRecSaveTime [MAX_VALS_TO_SAVE]; FLMUINT uiOldestSaved; FLMUINT uiIndexingRate; FLMBOOL bShowTime; F_MUTEX hScreenMutex; FTX_SCREEN * pScreen; FTX_WINDOW * pLogWin; FFILE * pFile; } IX_DISPLAY_INFO; FSTATIC RCODE ixDisplayHook( FTX_WINDOW * pWin, FLMBOOL bSelected, FLMUINT uiRow, FLMUINT uiKey, void * pvData, FLMUINT uiDataLen, F_DynamicList* pDynamicList ) { eColorType uiBack = FLM_CYAN; eColorType uiFore = FLM_WHITE; IX_DISPLAY_INFO * pDispInfo = (IX_DISPLAY_INFO *)pvData; char szTmpBuf [100]; const char * pszState; FLMUINT uiGMT; F_UNREFERENCED_PARM( uiKey); F_UNREFERENCED_PARM( uiDataLen); flmAssert( uiDataLen == sizeof( IX_DISPLAY_INFO)); f_timeGetSeconds( &uiGMT ); if( pDispInfo->IndexStatus.bSuspended) { pszState = "Susp"; } else if( pDispInfo->IndexStatus.uiLastRecordIdIndexed == RECID_UNDEFINED) { pszState = "Onln"; } else { pszState = "Offln"; } if( pDispInfo->IndexStatus.uiLastRecordIdIndexed != RECID_UNDEFINED) { f_sprintf( szTmpBuf, "%.5u %-15.15s %-5.5s %-10u %-10u %-10u %-10u %-10u", (unsigned)uiKey, pDispInfo->szName, pszState, (unsigned)pDispInfo->IndexStatus.uiLastRecordIdIndexed, (unsigned)pDispInfo->uiIndexingRate, (unsigned)pDispInfo->IndexStatus.uiKeysProcessed, (unsigned)pDispInfo->IndexStatus.uiRecordsProcessed, (unsigned)(pDispInfo->bShowTime ? pDispInfo->IndexStatus.uiStartTime ? uiGMT - pDispInfo->IndexStatus.uiStartTime : 0 : pDispInfo->IndexStatus.uiTransactions)); } else { f_sprintf( szTmpBuf, "%.5u %-15.15s %-5.5s %-10u", (unsigned)uiKey, pDispInfo->szName, pszState, (unsigned)(pDispInfo->bShowTime ? pDispInfo->IndexStatus.uiStartTime ? uiGMT - pDispInfo->IndexStatus.uiStartTime : 0 : pDispInfo->IndexStatus.uiTransactions)); } FTXWinSetCursorPos( pWin, 0, uiRow); FTXWinClearToEOL( pWin); FTXWinPrintf( pWin, "%s", szTmpBuf); if( bSelected && pDynamicList->getShowHorizontalSelector()) { FTXWinPaintRow( pWin, &uiBack, &uiFore, uiRow); } return( FERR_OK); } /**************************************************************************** Desc: Event callback *****************************************************************************/ FSTATIC void flstIndexUpdateEventHook( FEventType eEventType, void * pvAppData, void * pvEventData1, void * pvEventData2) { FDB * pDb = NULL; RCODE rc = FERR_OK; if( eEventType == F_EVENT_INDEXING_COMPLETE) { IX_DISPLAY_INFO * pDispInfo = (IX_DISPLAY_INFO *)pvAppData; FLMUINT uiIndexNum = (FLMUINT)pvEventData1; FINDEX_STATUS ixStatus; FLMUINT uiGMT; if( !pvEventData2) { if( RC_BAD( rc = flmOpenFile( pDispInfo->pFile, NULL, NULL, NULL, 0, TRUE, NULL, NULL, pDispInfo->pFile->pszDbPassword, &pDb))) { goto Exit; } FlmIndexStatus( (HFDB)pDb, uiIndexNum, &ixStatus); f_timeGetSeconds( &uiGMT ); f_mutexLock( pDispInfo->hScreenMutex); FTXWinPrintf( pDispInfo->pLogWin, "Index %u came on-line. Elapsed time = %u second(s)\n", uiIndexNum, uiGMT - ixStatus.uiStartTime); f_mutexUnlock( pDispInfo->hScreenMutex); } } Exit: if( pDb) { (void)FlmDbClose( (HFDB *) &pDb); } } /**************************************************************************** Desc: Thread that displays the current status of all indexes in a database Note: The caller must open the database and pass a handle to the thread. The handle will be closed when the thread exits. *****************************************************************************/ RCODE FLMAPI flstIndexManagerThread( IF_Thread * pThread) { F_DynamicList * pList = f_new F_DynamicList; FTX_WINDOW * pTitleWin; FTX_WINDOW * pListWin; FTX_WINDOW * pHeaderWin; FTX_WINDOW * pMsgWin; char szName[ 100]; FLMUINT uiIterations = 0; FLMUINT uiScreenCols; FLMUINT uiScreenRows; FLMUINT uiDrn; FLMUINT uiBufLen; FLMUINT uiUpdateInterval; FLMUINT uiLastUpdateTime; IX_DISPLAY_INFO IxDispInfo; FlmRecord * pRec = NULL; DLIST_NODE * pTmpNd; FLMUINT uiKey; FLMBOOL bShowOnline = TRUE; HFDB hDb = (HFDB)pThread->getParm1(); IX_DISPLAY_INFO * pDispInfo; FLMUINT uiOneSec; FLMBOOL bScreenLocked = FALSE; HFEVENT hEvent = HFEVENT_NULL; #define FIMT_TITLE_HEIGHT 1 #define FIMT_HEADER_HEIGHT 4 #define FIMT_LOG_HEIGHT 10 f_memset( &IxDispInfo, 0, sizeof( IX_DISPLAY_INFO)); IxDispInfo.hScreenMutex = F_MUTEX_NULL; IxDispInfo.pFile = ((FDB *)hDb)->pFile; IxDispInfo.bShowTime = TRUE; if( RC_BAD( f_mutexCreate( &IxDispInfo.hScreenMutex))) { goto Exit; } if( RC_BAD( FTXScreenInit( "Index Manager", &IxDispInfo.pScreen))) { goto Exit; } FTXScreenGetSize( IxDispInfo.pScreen, &uiScreenCols, &uiScreenRows); FTXScreenDisplay( IxDispInfo.pScreen); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, 0, FIMT_TITLE_HEIGHT, &pTitleWin))) { goto Exit; } FTXWinSetBackFore( pTitleWin, FLM_RED, FLM_WHITE); FTXWinClear( pTitleWin); FTXWinPrintStr( pTitleWin, "FLAIM Index Manager"); FTXWinSetCursorType( pTitleWin, FLM_CURSOR_INVISIBLE); FTXWinOpen( pTitleWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, FIMT_HEADER_HEIGHT, &pHeaderWin))) { goto Exit; } FTXWinMove( pHeaderWin, 0, FIMT_TITLE_HEIGHT); FTXWinSetBackFore( pHeaderWin, FLM_BLUE, FLM_WHITE); FTXWinClear( pHeaderWin); FTXWinSetCursorType( pHeaderWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHeaderWin, FALSE); FTXWinSetLineWrap( pHeaderWin, FALSE); FTXWinOpen( pHeaderWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, uiScreenRows - FIMT_TITLE_HEIGHT - FIMT_HEADER_HEIGHT - FIMT_LOG_HEIGHT, &pListWin))) { goto Exit; } FTXWinMove( pListWin, 0, FIMT_TITLE_HEIGHT + FIMT_HEADER_HEIGHT); FTXWinOpen( pListWin); pList->setup( pListWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, FIMT_LOG_HEIGHT, &IxDispInfo.pLogWin))) { goto Exit; } FTXWinDrawBorder( IxDispInfo.pLogWin); FTXWinMove( IxDispInfo.pLogWin, 0, uiScreenRows - FIMT_LOG_HEIGHT); FTXWinSetBackFore( IxDispInfo.pLogWin, FLM_BLUE, FLM_WHITE); FTXWinClear( IxDispInfo.pLogWin); FTXWinSetCursorType( IxDispInfo.pLogWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( IxDispInfo.pLogWin, TRUE); FTXWinSetLineWrap( IxDispInfo.pLogWin, FALSE); FTXWinOpen( IxDispInfo.pLogWin); FlmRegisterForEvent( F_EVENT_UPDATES, flstIndexUpdateEventHook, &IxDispInfo, &hEvent); FTXWinSetFocus( pListWin); uiIterations = 0; uiUpdateInterval = FLM_SECS_TO_TIMER_UNITS( 1); uiOneSec = FLM_SECS_TO_TIMER_UNITS( 1); uiLastUpdateTime = 0; while( !gv_bShutdown) { FLMUINT uiCurrTime = FLM_GET_TIMER(); if( bScreenLocked) { f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; } if( FLM_ELAPSED_TIME( uiCurrTime, uiLastUpdateTime) >= uiUpdateInterval) { Update_Screen: if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } FTXWinSetCursorPos( pHeaderWin, 0, 1); if( IxDispInfo.bShowTime) { FTXWinPrintf( pHeaderWin, "Index Index State Last Rate Keys Records Time"); } else { FTXWinPrintf( pHeaderWin, "Index Index State Last Rate Keys Records Trans"); } FTXWinClearToEOL( pHeaderWin); FTXWinPrintf( pHeaderWin, "\n"); FTXWinPrintf( pHeaderWin, "Num. Name DRN"); FlmDbTransBegin( hDb, FLM_READ_TRANS, 0); pTmpNd = pList->getFirst(); uiDrn = 0; for( ;;) { if( RC_BAD( FlmIndexGetNext( hDb, &uiDrn))) { break; } // Remove all invalid entries while( pTmpNd && pTmpNd->uiKey < uiDrn) { uiKey = pTmpNd->uiKey; pTmpNd = pTmpNd->pNext; pList->remove( uiKey); } FlmIndexStatus( hDb, uiDrn, &IxDispInfo.IndexStatus); if( !bShowOnline && !IxDispInfo.IndexStatus.bSuspended && IxDispInfo.IndexStatus.uiLastRecordIdIndexed == RECID_UNDEFINED) { if( pTmpNd && pTmpNd->uiKey == uiDrn) { uiKey = pTmpNd->uiKey; pTmpNd = pTmpNd->pNext; pList->remove( uiKey); } continue; } if( pTmpNd && pTmpNd->uiKey == uiDrn) { FLMUINT uiOldest; FLMUINT uiElapsed; pDispInfo = (IX_DISPLAY_INFO *)pTmpNd->pvData; f_strcpy( IxDispInfo.szName, pDispInfo->szName); // Copy the saved information. f_memcpy( &IxDispInfo.uiSaveRecsProcessed [0], &pDispInfo->uiSaveRecsProcessed [0], sizeof( FLMUINT) * MAX_VALS_TO_SAVE); f_memcpy( &IxDispInfo.uiRecSaveTime [0], &pDispInfo->uiRecSaveTime [0], sizeof( FLMUINT) * MAX_VALS_TO_SAVE); uiOldest = IxDispInfo.uiOldestSaved = pDispInfo->uiOldestSaved; // Recalculate the indexing rate. uiCurrTime = FLM_GET_TIMER(); uiElapsed = (uiCurrTime - IxDispInfo.uiRecSaveTime [uiOldest]) / uiOneSec; if (uiElapsed && IxDispInfo.IndexStatus.uiRecordsProcessed) { if( IxDispInfo.uiSaveRecsProcessed[ uiOldest] < IxDispInfo.IndexStatus.uiRecordsProcessed) { IxDispInfo.uiIndexingRate = // Records processed in time period (IxDispInfo.IndexStatus.uiRecordsProcessed - IxDispInfo.uiSaveRecsProcessed [uiOldest]) / uiElapsed; } else { IxDispInfo.uiIndexingRate = 0; } } else { IxDispInfo.uiIndexingRate = 0; } // Overwrite the oldest with the current data. IxDispInfo.uiRecSaveTime [uiOldest] = uiCurrTime; IxDispInfo.uiSaveRecsProcessed [uiOldest] = IxDispInfo.IndexStatus.uiRecordsProcessed; // Move oldest pointer for next update. if (++IxDispInfo.uiOldestSaved == MAX_VALS_TO_SAVE) { IxDispInfo.uiOldestSaved = 0; } } else { FLMUINT uiLoop; uiCurrTime = FLM_GET_TIMER(); IxDispInfo.uiIndexingRate = 0; for (uiLoop = 0; uiLoop < MAX_VALS_TO_SAVE; uiLoop++) { IxDispInfo.uiSaveRecsProcessed [uiLoop] = IxDispInfo.IndexStatus.uiRecordsProcessed; IxDispInfo.uiRecSaveTime [uiLoop] = uiCurrTime; } IxDispInfo.uiOldestSaved = 0; // Only retrieve the index name if we don't already have it. if( RC_BAD( FlmRecordRetrieve( hDb, FLM_DICT_CONTAINER, uiDrn, FO_EXACT, &pRec, &uiDrn))) { break; } flmAssert( pRec->getFieldID( pRec->root()) == FLM_INDEX_TAG); uiBufLen = sizeof( szName); pRec->getNative( pRec->root(), szName, &uiBufLen); if (uiBufLen >= sizeof( IxDispInfo.szName) - 1) { uiBufLen = sizeof( IxDispInfo.szName) - 1; szName [uiBufLen] = 0; } f_memcpy( IxDispInfo.szName, szName, uiBufLen); IxDispInfo.szName [uiBufLen] = 0; } pList->update( uiDrn, ixDisplayHook, &IxDispInfo, sizeof( IxDispInfo)); pList->refresh(); if( pTmpNd && pTmpNd->uiKey == uiDrn) { pTmpNd = pTmpNd->pNext; } } FlmDbTransAbort( hDb); uiLastUpdateTime = FLM_GET_TIMER(); pList->refresh(); } if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } if( RC_OK( FTXWinTestKB( pListWin))) { FLMUINT uiChar; FTXWinInputChar( pListWin, &uiChar); f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; switch( uiChar) { case 'O': case 'o': { bShowOnline = !bShowOnline; goto Update_Screen; } case '+': case 'r': { if( (pTmpNd = pList->getCurrent()) != NULL) { FlmIndexResume( hDb, pTmpNd->uiKey); goto Update_Screen; } break; } case 's': { if( (pTmpNd = pList->getCurrent()) != NULL) { FlmIndexSuspend( hDb, pTmpNd->uiKey); goto Update_Screen; } break; } case FKB_ALT_S: case 'S': { f_mutexLock( IxDispInfo.hScreenMutex); FTXMessageWindow( IxDispInfo.pScreen, FLM_RED, FLM_WHITE, "Suspending all indexes ....", NULL, &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); if (RC_OK( FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, 15))) { uiDrn = 0; for( ;;) { if( RC_BAD( FlmIndexGetNext( hDb, &uiDrn))) { break; } FlmIndexSuspend( hDb, uiDrn); } FlmDbTransCommit( hDb); } if( pMsgWin) { f_mutexLock( IxDispInfo.hScreenMutex); FTXWinFree( &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); } goto Update_Screen; } case 'R': case FKB_ALT_R: { f_mutexLock( IxDispInfo.hScreenMutex); FTXMessageWindow( IxDispInfo.pScreen, FLM_RED, FLM_WHITE, "Resuming all indexes ", NULL, &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); if (RC_OK( FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, 15))) { uiDrn = 0; for( ;;) { if( RC_BAD( FlmIndexGetNext( hDb, &uiDrn))) { break; } FlmIndexResume( hDb, uiDrn); } FlmDbTransCommit( hDb); } if( pMsgWin) { f_mutexLock( IxDispInfo.hScreenMutex); FTXWinFree( &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); } goto Update_Screen; } case 'T': case 't': { IxDispInfo.bShowTime = !IxDispInfo.bShowTime; goto Update_Screen; } case '?': { FTX_WINDOW * pHelpWin = NULL; FTX_WINDOW * pHelpTitle = NULL; F_DynamicList * pHelpList = NULL; FLMUINT uiItem = 0; char szTmpBuf [100]; f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; if( (pHelpList = f_new F_DynamicList) == NULL) { goto Help_Exit; } if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, 1, &pHelpTitle))) { goto Help_Exit; } FTXWinSetBackFore( pHelpTitle, FLM_RED, FLM_WHITE); FTXWinClear( pHelpTitle); FTXWinSetCursorType( pHelpTitle, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHelpTitle, FALSE); FTXWinSetLineWrap( pHelpTitle, FALSE); FTXWinPrintf( pHelpTitle, "FLAIM Index Manager - Help"); FTXWinOpen( pHelpTitle); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, uiScreenRows - 1, &pHelpWin))) { goto Help_Exit; } FTXWinDrawBorder( pHelpWin); FTXWinOpen( pHelpWin); pHelpList->setup( pHelpWin); f_sprintf( szTmpBuf, "R, ALT_R Resume all indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "S, ALT_S Suspend all indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "o, O Toggle display of on-line indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "+, r Resume selected index with auto on-line option"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "s Suspend selected index"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); pHelpList->refresh(); pHelpWin = pHelpList->getListWin(); f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; while( !gv_bShutdown) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; if( RC_OK( FTXWinTestKB( pHelpWin))) { FLMUINT uiTmpChar; FTXWinInputChar( pHelpWin, &uiTmpChar); if( uiTmpChar == FKB_ESCAPE) { break; } pHelpList->defaultKeyAction( uiTmpChar); } f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; f_sleep( 10); } Help_Exit: if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } if( pHelpList) { pHelpList->Release(); } if( pHelpTitle) { FTXWinFree( &pHelpTitle); } f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; break; } case FKB_ESCAPE: { goto Exit; } default: { f_mutexLock( IxDispInfo.hScreenMutex); pList->defaultKeyAction( uiChar); f_mutexUnlock( IxDispInfo.hScreenMutex); break; } } f_mutexLock( IxDispInfo.hScreenMutex); pList->refresh(); f_mutexUnlock( IxDispInfo.hScreenMutex); } uiIterations++; if( pThread->getShutdownFlag()) { break; } f_sleep( 1); } Exit: if( pList) { pList->Release(); } if( hEvent != HFEVENT_NULL) { FlmDeregisterForEvent( &hEvent); } if( IxDispInfo.pScreen) { FTXScreenFree( &IxDispInfo.pScreen); } if( IxDispInfo.hScreenMutex != F_MUTEX_NULL) { f_mutexDestroy( &IxDispInfo.hScreenMutex); } if( pRec) { pRec->Release(); } if( hDb != HFDB_NULL) { FlmDbClose( &hDb); } return( FERR_OK); } /**************************************************************************** Desc: Thread that displays the current status of a database's cache Note: The caller must pass a valid share handle to the thread on startup. *****************************************************************************/ RCODE FLMAPI flstMemoryManagerThread( IF_Thread * pThread) { F_DynamicList * pList = f_new F_DynamicList; FTX_SCREEN * pScreen; FTX_WINDOW * pTitleWin; FTX_WINDOW * pListWin; FTX_WINDOW * pHeaderWin; char szTmpBuf[ 80]; FLMUINT uiLoop; FLMUINT uiIteration = 0; FLMUINT uiScreenCols; FLMUINT uiScreenRows; FLM_MEM_INFO CacheInfo; CS_CONTEXT * pCSContext = NULL; FCL_WIRE Wire; NODE * pTree; F_Pool pool; #define FMMT_TITLE_HEIGHT 1 #define FMMT_HEADER_HEIGHT 3 if( RC_BAD( FTXScreenInit( "Memory Manager", &pScreen))) { goto Exit; } FTXScreenGetSize( pScreen, &uiScreenCols, &uiScreenRows); FTXScreenDisplay( pScreen); if( RC_BAD( FTXWinInit( pScreen, 0, FMMT_TITLE_HEIGHT, &pTitleWin))) { goto Exit; } FTXWinPaintBackground( pTitleWin, FLM_RED); FTXWinPrintStr( pTitleWin, "FLAIM Memory Manager"); FTXWinSetCursorType( pTitleWin, FLM_CURSOR_INVISIBLE); FTXWinOpen( pTitleWin); if( RC_BAD( FTXWinInit( pScreen, uiScreenCols, FMMT_HEADER_HEIGHT, &pHeaderWin))) { goto Exit; } FTXWinSetBackFore( pHeaderWin, FLM_BLUE, FLM_WHITE); FTXWinClear( pHeaderWin); FTXWinPrintf( pHeaderWin, "\n Record Block Both"); FTXWinSetCursorType( pHeaderWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHeaderWin, FALSE); FTXWinSetLineWrap( pHeaderWin, FALSE); FTXWinMove( pHeaderWin, 0, FMMT_TITLE_HEIGHT); FTXWinOpen( pHeaderWin); if( RC_BAD( FTXWinInit( pScreen, uiScreenCols, uiScreenRows - FMMT_TITLE_HEIGHT - FMMT_HEADER_HEIGHT, &pListWin))) { goto Exit; } FTXWinMove( pListWin, 0, FMMT_TITLE_HEIGHT + FMMT_HEADER_HEIGHT); FTXWinOpen( pListWin); pList->setup( pListWin); pool.poolInit( 1024); uiLoop = 0; while( !gv_bShutdown) { if( !(uiIteration % 100)) { FLMUINT uiKey = 0; FLM_CACHE_USAGE * pRecCacheUse = &CacheInfo.RecordCache; FLM_CACHE_USAGE * pBlkCacheUse = &CacheInfo.BlockCache; if( pCSContext) { Wire.setContext( pCSContext); /* Send a request get statistics */ if (RC_BAD( Wire.sendOp( FCS_OPCLASS_GLOBAL, FCS_OP_GLOBAL_MEM_INFO_GET))) { goto Exit; } if (RC_BAD( Wire.sendTerminate())) { goto Transmission_Error; } /* Read the response. */ if (RC_BAD( Wire.read())) { goto Transmission_Error; } if (RC_BAD( Wire.getRCode())) { goto Exit; } pool.poolReset( NULL); if( RC_BAD( Wire.getHTD( &pool, &pTree))) { goto Exit; } if( RC_BAD( fcsExtractMemInfo( pTree, &CacheInfo))) { goto Exit; } } else { FlmGetMemoryInfo( &CacheInfo); } f_sprintf( szTmpBuf, " Max Bytes ........................ %10u %10u", (unsigned)pRecCacheUse->uiMaxBytes, (unsigned)pBlkCacheUse->uiMaxBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Count ............................ %10u %10u", (unsigned)pRecCacheUse->uiCount, (unsigned)pBlkCacheUse->uiCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Total Bytes Allocated ............ %10u %10u", (unsigned)pRecCacheUse->uiTotalBytesAllocated, (unsigned)pBlkCacheUse->uiTotalBytesAllocated); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Hits ....................... %10u %10u", (unsigned)pRecCacheUse->uiCacheHits, (unsigned)pBlkCacheUse->uiCacheHits); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Hit Looks .................. %10u %10u", (unsigned)pRecCacheUse->uiCacheHitLooks, (unsigned)pBlkCacheUse->uiCacheHitLooks); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Faults ..................... %10u %10u", (unsigned)pRecCacheUse->uiCacheFaults, (unsigned)pBlkCacheUse->uiCacheFaults); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Fault Looks ................ %10u %10u", (unsigned)pRecCacheUse->uiCacheFaultLooks, (unsigned)pBlkCacheUse->uiCacheFaultLooks); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Dirty Count ...................... N/A %10u", (unsigned)CacheInfo.uiDirtyCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Dirty Bytes ...................... N/A %10u", (unsigned)CacheInfo.uiDirtyBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " New Count ........................ N/A %10u", (unsigned)CacheInfo.uiNewCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " New Bytes ........................ N/A %10u", (unsigned)CacheInfo.uiNewBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Log Count ........................ N/A %10u", (unsigned)CacheInfo.uiLogCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Log Bytes ........................ N/A %10u", (unsigned)CacheInfo.uiLogBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Old Version Count ................ %10u %10u", (unsigned)pRecCacheUse->uiOldVerCount, (unsigned)pBlkCacheUse->uiOldVerCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Old Version Bytes ................ %10u %10u", (unsigned)pRecCacheUse->uiOldVerBytes, (unsigned)pBlkCacheUse->uiOldVerBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Free Count ....................... N/A %10u", (unsigned)CacheInfo.uiFreeCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Free Bytes ....................... N/A %10u", (unsigned)CacheInfo.uiFreeBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Replaceable Count ................ N/A %10u", (unsigned)CacheInfo.uiReplaceableCount); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Replaceable Bytes ................ N/A %10u", (unsigned)CacheInfo.uiReplaceableBytes); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Dynamic Cache Adjust ............. %s", (CacheInfo.bDynamicCacheAdjust ? "YES" : "NO")); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Adjust Percentage .......... %u", (unsigned)CacheInfo.uiCacheAdjustPercent); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Adjust Min ................. %u", (unsigned)CacheInfo.uiCacheAdjustMin); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Cache Adjust Min To Leave ........ %u", (unsigned)CacheInfo.uiCacheAdjustMinToLeave); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); pList->refresh(); } if( RC_OK( FTXWinTestKB( pListWin))) { FLMUINT uiChar; FTXWinInputChar( pListWin, &uiChar); switch( uiChar) { case 'R': case 'r': FlmConfig( FLM_RESET_STATS, (void *)0, (void *)0); break; case FKB_UP: pList->cursorUp(); break; case FKB_DOWN: pList->cursorDown(); break; case FKB_PGUP: pList->pageUp(); break; case FKB_PGDN: pList->pageDown(); break; case FKB_HOME: pList->home(); break; case FKB_END: pList->end(); break; case FKB_ESCAPE: goto Exit; } pList->refresh(); } if( pThread->getShutdownFlag()) { break; } f_sleep( 10); uiIteration++; } Exit: if( pList) { pList->Release(); } if( pCSContext) { flmCloseCSConnection( &pCSContext); } pool.poolFree(); if( pScreen) { FTXScreenFree( &pScreen); } return( FERR_OK); Transmission_Error: pCSContext->bConnectionGood = FALSE; goto Exit; } /**************************************************************************** Desc: Thread that displays the current status of a database's tracker thread *****************************************************************************/ RCODE FLMAPI flstTrackerMonitorThread( IF_Thread * pThread) { F_DynamicList * pList = f_new F_DynamicList; FTX_SCREEN * pScreen; FTX_WINDOW * pTitleWin; FTX_WINDOW * pListWin; FTX_WINDOW * pHeaderWin; char szTmpBuf[ 80]; FLMUINT uiScreenCols; FLMUINT uiScreenRows; HFDB hDb = (HFDB)pThread->getParm1(); FMAINT_STATUS maintStatus; #define FTMT_TITLE_HEIGHT 1 #define FTMT_HEADER_HEIGHT 3 if( RC_BAD( FTXScreenInit( "Tracker Monitor", &pScreen))) { goto Exit; } FTXScreenGetSize( pScreen, &uiScreenCols, &uiScreenRows); FTXScreenDisplay( pScreen); if( RC_BAD( FTXWinInit( pScreen, 0, FTMT_TITLE_HEIGHT, &pTitleWin))) { goto Exit; } FTXWinPaintBackground( pTitleWin, FLM_RED); FTXWinPrintStr( pTitleWin, "FLAIM Tracker Monitor"); FTXWinSetCursorType( pTitleWin, FLM_CURSOR_INVISIBLE); FTXWinOpen( pTitleWin); if( RC_BAD( FTXWinInit( pScreen, uiScreenCols, FTMT_HEADER_HEIGHT, &pHeaderWin))) { goto Exit; } FTXWinSetBackFore( pHeaderWin, FLM_BLUE, FLM_WHITE); FTXWinClear( pHeaderWin); FTXWinPrintf( pHeaderWin, "\nDescription"); FTXWinSetCursorType( pHeaderWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHeaderWin, FALSE); FTXWinSetLineWrap( pHeaderWin, FALSE); FTXWinMove( pHeaderWin, 0, FTMT_TITLE_HEIGHT); FTXWinOpen( pHeaderWin); if( RC_BAD( FTXWinInit( pScreen, uiScreenCols, uiScreenRows - FTMT_TITLE_HEIGHT - FTMT_HEADER_HEIGHT, &pListWin))) { goto Exit; } FTXWinMove( pListWin, 0, FTMT_TITLE_HEIGHT + FTMT_HEADER_HEIGHT); FTXWinOpen( pListWin); pList->setup( pListWin); while( !gv_bShutdown) { FLMUINT uiKey = 0; FlmMaintenanceStatus( hDb, &maintStatus); switch( maintStatus.eDoing) { case FLM_MAINT_IDLE: { f_sprintf( szTmpBuf, " Status ........................... Idle"); break; } case FLM_MAINT_LOOKING_FOR_WORK: { f_sprintf( szTmpBuf, " Status ........................... Looking for Work"); break; } case FLM_MAINT_WAITING_FOR_LOCK: { f_sprintf( szTmpBuf, " Status ........................... Waiting for Lock"); break; } case FLM_MAINT_ENDING_TRANS: { f_sprintf( szTmpBuf, " Status ........................... Ending Transaction"); break; } case FLM_MAINT_TERMINATED: { f_sprintf( szTmpBuf, " Status ........................... Terminated"); break; } case FLM_MAINT_FREEING_BLOCKS: { f_sprintf( szTmpBuf, " Status ........................... Freeing Blocks"); break; } default: { f_sprintf( szTmpBuf, " Status ........................... Unknown"); break; } } pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, " Blocks Freed ..................... %I64u", (FLMUINT64)maintStatus.ui64BlocksFreed); pList->update( uiKey++, NULL, szTmpBuf, sizeof( szTmpBuf)); if( RC_OK( FTXWinTestKB( pListWin))) { FLMUINT uiChar; FTXWinInputChar( pListWin, &uiChar); switch( uiChar) { case FKB_UP: pList->cursorUp(); break; case FKB_DOWN: pList->cursorDown(); break; case FKB_PGUP: pList->pageUp(); break; case FKB_PGDN: pList->pageDown(); break; case FKB_HOME: pList->home(); break; case FKB_END: pList->end(); break; case FKB_ESCAPE: goto Exit; } pList->refresh(); } if( pThread->getShutdownFlag()) { break; } pList->refresh(); f_sleep( 100); } Exit: if( pList) { pList->Release(); } if( pScreen) { FTXScreenFree( &pScreen); } if( hDb != HFDB_NULL) { FlmDbClose( &hDb); } return( FERR_OK); }