338 lines
11 KiB
C++
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( ¤tClock, 0x00, sizeof( struct timespec ) );
|
|
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
|
|
|
// 정보 설정.
|
|
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;
|
|
} |