#include "ProcessMonitoringThread.h" #include "Logger.h" #include "ProcessRename.h" #include #include #include #include #include #include // 정보 갱신 주기 (sec) // - rebalance 작업의 console 상태 정보는 2 sec 단위로 업데이트 한다. #define INTERVAL_UPDATE_INFO 2 // 생성자 CProcessMonitoringThread::CProcessMonitoringThread( CDataQueue * const pQueueMoveStandby , CDataQueue * const pQueueUpdateStandby , CDataQueue * const pQueueDeleteStandby , CCopyControlThread * const pCopyControlThread ) : m_pQueueMoveStandby( pQueueMoveStandby) , m_pQueueUpdateStandby( pQueueUpdateStandby) , m_pQueueDeleteStandby( pQueueDeleteStandby ) , m_pCopyControlThread( pCopyControlThread ) { // 멤버변수 초기화 m_threadHandle = 0; // thread handle 초기화 m_mapUnlinkInfo.clear(); pthread_mutex_init( &m_mutexUnlinkInfo, NULL ); } // 소멸자 CProcessMonitoringThread::~CProcessMonitoringThread() { // thread 가 동작 중인 경우.. thread 중지 처리 if( m_threadHandle != 0 ) { pthread_cancel( m_threadHandle ); } pthread_mutex_destroy( &m_mutexUnlinkInfo ); m_mapUnlinkInfo.clear(); // 혹시나 해서 정석대로 NULL 처리 추가함. if( m_pQueueMoveStandby != NULL ) m_pQueueMoveStandby = NULL; if( m_pQueueUpdateStandby != NULL ) m_pQueueUpdateStandby = NULL; if( m_pQueueDeleteStandby != NULL ) m_pQueueDeleteStandby = NULL; if( m_pCopyControlThread != NULL ) m_pCopyControlThread = NULL; } //////////////////////////////// bool CProcessMonitoringThread::Start() { // 멤버 변수 유효성 check if( m_pQueueMoveStandby == NULL || m_pQueueUpdateStandby == NULL || m_pQueueDeleteStandby == NULL ) { LOG( LERR, "ProcessMonitoringThread: queue object pointer not valid." ); return false; } if( m_pCopyControlThread == NULL ) { LOG( LERR, "ProcessMonitoringThread: copy thread object pointer not valid."); return false; } // 작업 thread 생성 int nResult = pthread_create( &m_threadHandle, NULL, CProcessMonitoringThread::threadFunc, this ); if( nResult != 0 ) { // thread 생성 실패 int errorNum = errno; LOG( LERR, "ProcessMonitoringThread: Thread create failed.[%d][%s]", errorNum, strerror( errorNum ) ); return false; } return true; } void CProcessMonitoringThread::UpdateTitle( void ) { char szTemp[100] = { 0 }; // 본 출력 사항에 대한 설명은 help 에 포함되어 있으므르 // 수정할 경우 PrintUsage(), Execute() 의 내역도 수정해야 함. sprintf( szTemp, "%s: S%u T%d U%u D%u" , PROG_NAME , m_pQueueMoveStandby->GetSize() , m_pCopyControlThread->GetCopyThreadCount() , m_pQueueUpdateStandby->GetSize() , m_pQueueDeleteStandby->GetSize() ); set_ps_display( szTemp, false ); return; } void CProcessMonitoringThread::UpdateDeletedInfo( CRebalanceData & data ) { // CPhysicalDeleteThread 에서 // 정상적으로 삭제 처리한 content 에 대한 FHS, 삭제 크기 정보를 전달받는다. // 전달받은 정보는 내부적으로 저장했다가 주기적으로 로깅 처리한다. std::map::iterator it; pthread_mutex_lock( &m_mutexUnlinkInfo ); it = m_mapUnlinkInfo.find( data.m_szOriginHost ); if( it != m_mapUnlinkInfo.end() ) { // 이미 해당 FHS 가 존재하는 경우... // - 해당 정보를 추가로 sum 처리한다... it->second.hour_count += 1; it->second.hour_sum += data.m_uOriginContentLength; it->second.day_count += 1; it->second.day_sum += data.m_uOriginContentLength; } else { // 해당 FHS 정보가 없는 경우... // - 신규로 추가한다. // - map 특성상 key 값에 의한 자동 sort 처리됨. struct FhsUnlinkInfo fhs; fhs.hour_count = 1; fhs.hour_sum = data.m_uOriginContentLength; fhs.day_count = 1; fhs.day_sum = data.m_uOriginContentLength; m_mapUnlinkInfo[ data.m_szOriginHost ] = fhs; } pthread_mutex_unlock( &m_mutexUnlinkInfo ); _LOG( LDBG, "ProcessMonitoringThread: deleted info update. [%s %s %llu]" , data.m_szOriginHost.c_str() , data.m_szServiceSeq.c_str() , data.m_uOriginContentLength ); return; } ////////////////////////////////////////////// // Thread loop 기본 함수 void * CProcessMonitoringThread::threadFunc( void * arg ) { CProcessMonitoringThread * pObject = reinterpret_cast( arg ); pthread_detach( pthread_self() ); while( 1 ) { pthread_testcancel(); pObject->Execute(); pthread_testcancel(); // 지정된 주기로 실행 sleep( INTERVAL_UPDATE_INFO ); } // thread 종료시 handle 정보 초기화 pObject->m_threadHandle = 0; return NULL; } // 실제 정보 update 처리 함수 void CProcessMonitoringThread::Execute() { char szTemp[100] = { 0 }; unsigned int nCountMoveStandby = m_pQueueMoveStandby->GetSize(); unsigned int nCountUpdateStandby = m_pQueueUpdateStandby->GetSize(); unsigned int nCountDeleteStandby = m_pQueueDeleteStandby->GetSize(); int nCountContentTransferThread = m_pCopyControlThread->GetCopyThreadCount(); int nCountMaxContentTransferThread = 0; // 본 출력 사항에 대한 설명은 help 에 포함되어 있으므르 // 수정할 경우 PrintUsage(),UpdateTitle() 의 내역도 수정해야 함. sprintf( szTemp, "%s: S%u T%d U%u D%u" , PROG_NAME , nCountMoveStandby , nCountContentTransferThread , nCountUpdateStandby , nCountDeleteStandby ); set_ps_display( szTemp, false ); if( nCountMoveStandby != 0 || nCountContentTransferThread != 0 || nCountUpdateStandby != 0 || nCountDeleteStandby != 0 ) { nCountMaxContentTransferThread = m_pCopyControlThread->GetMaxCopyThreadCount(); _LOG( LINF, "[MONITOR] Move standby: %4u, Transfer thread: %d/%d, Update standby: %4u, Unlink standby: %4u" , nCountMoveStandby , nCountContentTransferThread, nCountMaxContentTransferThread , nCountUpdateStandby , nCountDeleteStandby ); } // 각 FHS 별 삭제한 통계 정보를 logging 및 초기화 처리수행. printUnlinkInfo(); return; } void CProcessMonitoringThread::printUnlinkInfo() { if( m_mapUnlinkInfo.empty() == true ) return; // 시간 check // - 시간 단위로 FHS 별 삭제한 정보를 로깅하고 초기화. // - 일 단위 FHS 별 삭제한 정보는 매일 10시에 로깅 및 초기화 되도록 한다. time_t currentTime = time( NULL ); long currentSec = currentTime % 3600; // 1시간 = 3600 sec 로 나누어서 나머지가 현재 시간의 sec 를 나타냄 if( currentSec == 0 || currentSec == 1 ) // 각 시간 정각 또는 정각+1 sec { // total 정보 출력을 위한 변수 unsigned long long uTotalFhsCount = 0; unsigned long long uTotalContentCount = 0; unsigned long long uTotalContentSum = 0; std::map::iterator it;; struct tm currentTm; memset( ¤tTm, 0x00, sizeof( struct tm ) ); localtime_r( ¤tTime, ¤tTm ); if( currentTm.tm_hour == 10 ) { // 오전 9시 정각에는 full logging. pthread_mutex_lock( &m_mutexUnlinkInfo ); for( it = m_mapUnlinkInfo.begin(); it != m_mapUnlinkInfo.end(); it++ ) { uTotalFhsCount += 1; uTotalContentCount += it->second.day_count; uTotalContentSum += it->second.day_sum; // FHS 별 확보한 용량 통계 정보 출력 _LOG( LINF, "[MONITOR] FHS rebalance day report:: %s , count:%5lu , size:%5llu GiB." , it->first.c_str() , it->second.day_count, (it->second.day_sum)/1024/1024/1024 ); } // 통계 정보 초기화 m_mapUnlinkInfo.clear(); pthread_mutex_unlock( &m_mutexUnlinkInfo ); // total report logging _LOG( LINF, "[MONITOR] FHS rebalance total day report:: fhs: %llu , content: %llu , total_size: %llu GiB." , uTotalFhsCount , uTotalContentCount , uTotalContentSum / 1024 / 1024 / 1024 ); } else { // 나머지는 시간당 삭제 처리한 정보 로깅 pthread_mutex_lock( &m_mutexUnlinkInfo ); for( it = m_mapUnlinkInfo.begin(); it != m_mapUnlinkInfo.end(); it++ ) { // 해당 시간에 작업하지 않은 FHS 는 제외 if( it->second.hour_count > 0 ) { uTotalFhsCount += 1; uTotalContentCount += it->second.hour_count; uTotalContentSum += it->second.hour_sum; // FHS 별 확보한 용량 통계 정보 출력 _LOG( LINF, "[MONITOR] FHS rebalance hour report:: %s , count:%5lu , size:%5llu GiB." , it->first.c_str() , it->second.hour_count, (it->second.hour_sum) / 1024 / 1024 / 1024 ); // 각 장비 시간 단위 통계 정보 초기화 it->second.hour_count = 0; it->second.hour_sum = 0; } } pthread_mutex_unlock( &m_mutexUnlinkInfo ); // total report logging _LOG( LINF, "[MONITOR] FHS rebalance total hour report:: fhs: %llu , content: %llu , total_size: %llu GiB." , uTotalFhsCount , uTotalContentCount , uTotalContentSum / 1024 / 1024 / 1024 ); } } return; }