Files
interactive/rcts/rc_mond/src/ShmClientInfo.cpp
T
2026-08-07 17:38:18 +09:00

338 lines
11 KiB
C++

#include "ShmClientInfo.h"
#include "Logger.h"
#include "ProcessConfig.h"
#include "ReportLog.h"
#include <string.h>
// 2018-02-22 CHG huibong FHS Disk busy 상황시 report 로깅을 위한 기준값
#define REPORT_MAX_DISK_QUEUE 10 // disk queue 값이 해당 정의 값 이상인 경우
#define REPORT_MAX_DISK_BUSY 90.0 // disk busy 값이 해당 정의 값 이상인 경우
// 생성자
CShmClientInfo::CShmClientInfo( struct ClientInfo * p )
: m_pClient( p )
{
// 서비스 상태 code 에 대한 문자열 정보를 저장하기 위한 멤버 변수 설정.
// - may 객체이므로.. key - value 형식으로 저장 처리
m_mapServiceStatString[SERVICE_STAT_NOT_DEFINE] = "Not Define";
m_mapServiceStatString[SERVICE_STAT_OK] = "OK";
m_mapServiceStatString[SERVICE_STAT_OUT] = "Out";
m_mapServiceStatString[SERVICE_STAT_DISABLE] = "Disable";
m_mapServiceStatString[SERVICE_STAT_RONLY] = "Read-only";
// NEW 2018-01-11 huibong 메모리 사용량 초과시 report 기능 추가 (#31360, #31679)
// check 여부 판단을 위한 변수 초기화
if( CProcessConfig::GetInstance()->GetReportMemoryMaxUsage() > 0 )
m_bReportMemoryMaxUsage = true;
else
m_bReportMemoryMaxUsage = false;
m_iShmSystemUpdateCount = 0;
}
// 소멸자
CShmClientInfo::~CShmClientInfo()
{
}
// Service 상태 정보에 대한 문자열 반환.
const char * CShmClientInfo::GetServiceStatString( const int & stat )
{
std::map< int, std::string >::iterator pos;
pos = m_mapServiceStatString.find( stat );
if( pos != m_mapServiceStatString.end() )
{
// 해당 항목 존재시
return pos->second.c_str();
}
else
{
// 해당 항목이 존재하지 않는 경우.
return m_mapServiceStatString[SERVICE_STAT_NOT_DEFINE].c_str();
}
}
// 현재 Service 상태 정보에 대한 문자열 반환.
const char * CShmClientInfo::GetServiceStatString()
{
std::map< int, std::string >::iterator pos;
pos = m_mapServiceStatString.find( m_pClient->service.service_stat);
if( pos != m_mapServiceStatString.end() )
{
// 해당 항목 존재시
return pos->second.c_str();
}
else
{
// 해당 항목이 존재하지 않는 경우.
return m_mapServiceStatString[SERVICE_STAT_NOT_DEFINE].c_str();
}
}
// 공유 메모리 상태가 유효하지 여부 판단.
bool CShmClientInfo::IsValid( const char * pClientAddress ) const
{
if( m_pClient == NULL )
return false;
else
{
// 해당 공유메모리가 미사용 중으로 마킹된 경우...
if( m_pClient->use == 0 )
return false;
// 해당 공유메모리의 client IP 가 서로 다른 경우...
if( strcmp( pClientAddress, m_pClient->client_ip ) != 0 )
return false;
}
return true;
}
// serviceinfo 정보를 공유메모리에 저장 처리.
// return false : 공유메모리가 유효하지 않은 경우...
bool CShmClientInfo::UpdateServiceInfo( std::string & strHostname, int iServiceStat )
{
// 공유메모리가 유효하지 않은 경우..
if( m_pClient == NULL || m_pClient->use == 0 )
return false;
int iPreviousServiceStat = 0;
// 현재 시간 정보 추출.
time_t currentTime = time( 0 );
struct timespec currentClock;
memset( &currentClock, 0x00, sizeof( struct timespec ) );
clock_gettime( CLOCK_MONOTONIC, &currentClock );
// 정보 설정.
if( m_pClient->valid == 1 )
{
// hostname 정보 설정.
// - 기존 값과 비교하여 변경된 경우.. 관련 내역 로깅.
if( strcmp( m_pClient->hostname, strHostname.c_str() ) != 0 )
{
LOG( LWAR, "client [%s] hostname changed [%s] -> [%s].", m_pClient->client_ip, m_pClient->hostname, strHostname.c_str() );
// hostname 정보 복사
strncpy( m_pClient->hostname, strHostname.c_str(), HOST_NAME_LENGTH );
}
// 이전 서비스 상태 정보 저장
iPreviousServiceStat = m_pClient->service.service_stat;
// 서비스 상태 정보 변경 여부 관련 내역 로깅
if( iPreviousServiceStat != iServiceStat )
{
_LOG( LINF, "client[%s] hostname[%s] service stat changed. [%s] -> [%s]."
, m_pClient->client_ip, m_pClient->hostname, GetServiceStatString( iPreviousServiceStat ), GetServiceStatString( iServiceStat ) );
// 서비스 상태 정보 업데이트
m_pClient->service.service_stat = iServiceStat;
}
// update 시간 설정
m_pClient->service.update_time = currentTime;
m_pClient->service.update_time_clock_sec = currentClock.tv_sec;
// apllication 정보 설정.
m_pClient->client_app = 0;
// 2018-02-22 NEW huibong (#31703)
// - 운영 편의성을 위해 다음 상황을 report 로깅 처리한다.
// - 1. 서비스 상태가 OK , Read only 상태에서 Disable, OUT 상황으로 변경되는 경우
// - 2. 서비스 상태가 비정상 상황(disable, out) 상황에서 정상( ok, read only) 상황으로 변경되는 경우
// 서비스 상태가 변경된 경우 - 대부분 상태 변경은 잘 일어나지 않으므로.. 빠른 로직 검사를 위해 불필요해도 넣어 둠
if( iPreviousServiceStat != iServiceStat )
{
// 현재 상태가 비정상 상황인 경우
if( iServiceStat == SERVICE_STAT_OUT || iServiceStat == SERVICE_STAT_DISABLE )
{
// 이전 상황은 정상인 경우
if( iPreviousServiceStat != SERVICE_STAT_OUT && iPreviousServiceStat != SERVICE_STAT_DISABLE )
{
// report 로깅 객체 생성
CReportLog reportLog;
std::string strErrorMessage;
strErrorMessage.clear();
if( reportLog.Init( CProcessConfig::GetInstance()->GetLogPath() ) == false )
{
reportLog.GetLastError( strErrorMessage );
LOG( LERR, "client[%s] service stat change log init failed.[%s]", strHostname.c_str(), strErrorMessage.c_str() );
}
else
{
reportLog.Write( "WAR", "[%s] [ %s, service stat changed. %s -> %s. check FHS status.]"
, PROG_NAME, strHostname.c_str()
, GetServiceStatString( iPreviousServiceStat ), GetServiceStatString( iServiceStat ) );
}
}
}
else
{
// 현재 상태가 OK, Read only 의 정상 상황인 경우
// 이전 상태가 비정상 상황인 경우
if( iPreviousServiceStat == SERVICE_STAT_OUT || iPreviousServiceStat == SERVICE_STAT_DISABLE )
{
// report 로깅 객체 생성
CReportLog reportLog;
std::string strErrorMessage;
strErrorMessage.clear();
if( reportLog.Init( CProcessConfig::GetInstance()->GetLogPath() ) == false )
{
reportLog.GetLastError( strErrorMessage );
LOG( LERR, "client[%s] service stat change log init failed.[%s]", strHostname.c_str(), strErrorMessage.c_str() );
}
else
{
reportLog.Write( "INF", "[%s] [ %s, service stat changed. %s -> %s. ]"
, PROG_NAME, strHostname.c_str()
, GetServiceStatString( iPreviousServiceStat ), GetServiceStatString( iServiceStat ) );
}
}
}
}
}
else
{
// hostname 정보 설정.
strncpy( m_pClient->hostname, strHostname.c_str(), HOST_NAME_LENGTH );
// 서비스 상태 정보 설정.
m_pClient->service.service_stat = iServiceStat;
// update 시간 설정
m_pClient->service.update_time = currentTime;
m_pClient->service.update_time_clock_sec = currentClock.tv_sec;
// apllication 정보 설정.
m_pClient->client_app = 0;
// Data 유효 여부 설정.
m_pClient->valid = 1;
}
return true;
}
// systeminfo 정보를 공유메모리에 저장 처리.
// return false : 공유메모리가 유효하지 않거나... valid 가 유효하지 않거나.. hostname 이 동일하지 않은 경우.
bool CShmClientInfo::UpdateSystemInfo( std::string & strHostname, struct SystemInfo * pData )
{
// 공유메모리가 유효하지 않은 경우..
if( m_pClient == NULL || m_pClient->use == 0 )
return false;
// 현재 시간 정보 추출.
time_t currentTime = time( 0 );
// valid 설정값이 유효하지 않은 경우..
// - service info 정보가 먼저 기록되지 않은 상태인 경우....
// - 정보를 기록하지 않는다.
if( m_pClient->valid == 0 )
{
LOG( LWAR, "client [%s] hostname[%s] info not valid. [%d].", m_pClient->client_ip, m_pClient->hostname, m_pClient->valid );
return false;
}
// hostname 정보가 동일한지 검사.
if( strcmp( m_pClient->hostname, strHostname.c_str() ) != 0 )
{
LOG( LWAR, "client [%s] hostname[%s] not match. [%s].", m_pClient->client_ip, m_pClient->hostname, strHostname.c_str() );
return false;
}
// 정보가 동일한 경우.... copy 처리
memcpy( &(m_pClient->system), pData, sizeof( struct SystemInfo ) );
m_pClient->system.update_time = currentTime;
// 2018-02-22 CHG huibong (#31703)
// - 2018-01-12 #31544, #31679 에 의해 추가된 다음 기능 제거
// -- FHS Disk hang 또는 이상 상황으로 disk busy 비정상 증가시 자동 FHS out 처리
// - 사유
// -- Disk Hang 이 아닌 상황에서도 기준값(queue 10 & busy 90%)을 초과하는 Disk Busy 상황 발생으로 잘못된 서비스 OUT 발생 가능
// - 기타
// -- Disk busy 상황시 Report 로깅 처리 기능은 유지
// -- Disk busy 판단 기준값은 그대로 유지 queue 10, busy 90%
// -- 참고로 FHS 는 queue 7, busy 50% 이상인 경우 자동으로 read only 로 변경 처리됨
// --- FHS 와 같은 기준값을 사용하지 않은 이유는 FHS 기준값은 순간적인 응답지연을 막기 위한 최소한의 기준값이기 때문.
// 현재 상태가 out, disable 상태가 아닌 정상 상황인 경우
if( m_pClient->service.service_stat != SERVICE_STAT_OUT && m_pClient->service.service_stat != SERVICE_STAT_DISABLE )
{
// system 상태가 정보가 disk busy 상황인 경우
if( pData->disk_max_queue >= REPORT_MAX_DISK_QUEUE && pData->disk_max_busy >= REPORT_MAX_DISK_BUSY )
{
// report 로깅 객체 생성
CReportLog reportLog;
std::string strErrorMessage;
strErrorMessage.clear();
if( reportLog.Init( CProcessConfig::GetInstance()->GetLogPath() ) == false )
{
reportLog.GetLastError( strErrorMessage );
LOG( LERR, "client[%s] disk busy report log init failed.[%s]", strHostname.c_str(), strErrorMessage.c_str() );
}
else
{
reportLog.Write( "WAR", "[%s] [ %s, disk busy too high. busy %4.1lf%% , queue %ju. check FHS status.]"
, PROG_NAME, strHostname.c_str(), pData->disk_max_busy, pData->disk_max_queue );
_LOG( LWAR, "client[%s] disk busy[%4.1lf %%] too high. queue[%ju]. report logging."
, strHostname.c_str(), pData->disk_max_busy, pData->disk_max_queue );
}
}
}
// NEW 2018-01-11 huibong 메모리 사용량 초과시 report 기능 추가 (#31360, #31679)
// - FHS memory 사용량이 지정된 값 이상인 경우 report 로깅 처리
// - FHS system 정보가 10 sec 마다 전송되므로.. 잦은 로깅 발생 가능
// - 따라서 분당 1회만 check 하도록 한다 (최초 요청은 기동시 초기화 이슈 있으므로.. 버리고.. 3번째 요청부터 체크)
if( m_bReportMemoryMaxUsage == true && m_iShmSystemUpdateCount % 6 == 2)
{
// FHS memory 사용률이 conf 설정값 이상인 경우.
if( pData->memory_usage >= CProcessConfig::GetInstance()->GetReportMemoryMaxUsage() )
{
CReportLog reportLog;
std::string strErrorMessage;
strErrorMessage.clear();
if( reportLog.Init( CProcessConfig::GetInstance()->GetLogPath() ) == false )
{
reportLog.GetLastError( strErrorMessage );
LOG( LERR, "client[%s] memory usage report log init failed.[%s]", strHostname.c_str(), strErrorMessage.c_str() );
}
else
{
reportLog.Write( "WAR", "[%s] [FHS (%s) memory usage too high = %d%%. total=%ju byte. free=%ju byte. check FHS status.]"
, PROG_NAME, strHostname.c_str(), pData->memory_usage, pData->memory_total, pData->memory_free );
_LOG( LWAR, "client[%s] memory usage[%d %%] too high. total[%ju] free[%ju]. report logging."
, strHostname.c_str(), pData->memory_usage, pData->memory_total, pData->memory_free );
}
}
}
// system 관련 shared memory update count 증가 처리
// - 10 sec 마다 업데이트 되므로.. 일 단위 count reset
m_iShmSystemUpdateCount++;
if( m_iShmSystemUpdateCount > 8640 )
m_iShmSystemUpdateCount = 0;
return true;
}