base
This commit is contained in:
@@ -0,0 +1,716 @@
|
||||
#include "ShmInfoThread.h"
|
||||
|
||||
#include "Logger.h"
|
||||
#include "Common.h"
|
||||
#include "ProcessConfig.h"
|
||||
#include "../rc_mond/ShmDefine.h"
|
||||
#include "../rc_mond/ShmControl.h"
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm> // vector sort 사용 목적
|
||||
|
||||
|
||||
// 매 Loop 마다 Sleep 시간 정보 정의 ( sec 단위)
|
||||
#define SLEEP_TIME_DEFAULT 20
|
||||
#define SLEEP_TIME_MAX 60
|
||||
|
||||
// rc_mond shared memory 접근을 위한 key 파일.
|
||||
#define RC_MOND_SHARED_MEMORY_KEY_FILE "/user/service/rc_mond.shm"
|
||||
|
||||
// Rebalance 처리 대상 FHS 관련 FHS 의 최소 Storage 사용률 제한값.
|
||||
// 해당 percent(%) 이상인 장비만 선정되도록 하기 위함
|
||||
#define REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT 50
|
||||
|
||||
// Rebalance 처리 대상 FHS 관련 FHS 의 최대 disk busy 제한값.
|
||||
// 해당 percent(%) 이하인 장비만 선정되도록 하기 위함
|
||||
#define REBALANCE_TARGET_DISK_MAX_BUSY_LIMIT 50.0
|
||||
|
||||
// Rebalance 대상 FHS 선정을 위한 score 계산시 disk_max_busy 항목에 부여할 가중치 정보.
|
||||
// - 점수가 높은 FHS 장비가 선정되므로...
|
||||
// - disk busy 상태인 장비는 선택되지 않도록 0.5 수준으로 설정
|
||||
// - storage_max_usage : disk_max_busy = 2 : 1 로 계산
|
||||
#define REBALANCE_TARGET_DISK_MAX_BUSY_WEIGHT 0.5
|
||||
|
||||
// Rebalance 대상 FHS 정보를 저장한 list 의 유효시간 (sec)
|
||||
// - SLEEP_TIME_MAX 값보다 커야 함.
|
||||
#define TIMEOUT_REBALANCE_LIST 120
|
||||
|
||||
// Copy 수신 가능 FHS 의 Disk 여유용량 최소값
|
||||
// - 1 TB
|
||||
#define COPY_TARGET_DISK_MIN_AVAILABLE_LIMIT (1099511627776ULL)
|
||||
|
||||
// COPY 수신 가능 FHS 선정을 위한 score 계산시 disk_max_busy 항목에 부여할 가중치 정보.
|
||||
// - 참고로 rc_mond 의 Top FHS 선정은 storage_max_usage : disk_max_busy = 1 : 4 로 계산하여 처리
|
||||
// - Copy Target 은 실제 copy 처리를 수행하는 thread 가 많지 않고...
|
||||
// - 되도록 여유 용량이 많은 장비에 copy 하는 것이 효과적이므로...
|
||||
// - storage_max_usage : disk_max_busy = 1 : 2 로 계산
|
||||
#define COPY_TARGET_DISK_MAX_BUSY_WEIGHT 2.0
|
||||
|
||||
// Copy 대상 FHS 정보를 저장한 list 의 유효시간 (sec)
|
||||
// - default sleep time 값보다 커야 함
|
||||
#define TIMEOUT_COPY_LIST 30
|
||||
|
||||
|
||||
// 공유메모리에 저장된 FHS 정보 중 적합한 FHS 정보를 찾기 위해
|
||||
// FHS 와 각 점수 정보를 저장하기 위한 구조체
|
||||
struct FhsScore {
|
||||
|
||||
char hostname[HOST_NAME_LENGTH + 1]; // hostname, NULL 포함 최대 64자까지만 허용됨.
|
||||
double score; // 계산된 score, 작을수록 idle
|
||||
};
|
||||
|
||||
|
||||
|
||||
CShmInfoThread::CShmInfoThread()
|
||||
{
|
||||
// 멤버변수 초기화
|
||||
m_threadHandle = 0;
|
||||
|
||||
m_uSleep = SLEEP_TIME_DEFAULT;
|
||||
|
||||
m_listRebalanceFhs.clear();
|
||||
m_listCopyTargetFhs.clear();
|
||||
|
||||
// 시간 정보 초기화.
|
||||
memset( &m_timeLastRefreshRebalanceFhs, 0x00, sizeof( struct timespec ) );
|
||||
memset( &m_timeLastRefreshCopyTargetFhs, 0x00, sizeof( struct timespec ) );
|
||||
|
||||
pthread_mutex_init( &m_mutexRebalanceFhs, NULL );
|
||||
pthread_mutex_init( &m_mutexCopyTargetFhs, NULL );
|
||||
|
||||
}
|
||||
|
||||
CShmInfoThread::~CShmInfoThread()
|
||||
{
|
||||
// thread 가 동작 중인 경우.. thread 중지 처리
|
||||
if( m_threadHandle != 0 )
|
||||
{
|
||||
pthread_cancel( m_threadHandle );
|
||||
}
|
||||
|
||||
sleep( 1 ); // thread 종료 잠시 대기
|
||||
|
||||
pthread_mutex_destroy( &m_mutexRebalanceFhs );
|
||||
pthread_mutex_destroy( &m_mutexCopyTargetFhs );
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
bool CShmInfoThread::Start()
|
||||
{
|
||||
// 작업 thread 생성
|
||||
int nResult = pthread_create( &m_threadHandle, NULL, CShmInfoThread::threadFunc, this );
|
||||
if( nResult != 0 )
|
||||
{
|
||||
// thread 생성 실패
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "[SHM INF] thread create failed.[%d][%s]", errorNum, strerror( errorNum ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShmInfoThread::GetRebalanceTargetFhs( std::string & szResultHost, std::list<std::string>& listIgnoreFHS )
|
||||
{
|
||||
// Rebalance 대상 FHS 목록 중....
|
||||
// 전달받은 listIgnoreFHS 에 등록된 FHS 정보를 제외하고....
|
||||
// 남은 FHS 정보 중.. 맨 처음 나오는 정보를 전달한다.
|
||||
|
||||
|
||||
// 1. 저장된 list 정보가 갱신이 되지 않아 오래된 경우.... 버린다.
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
|
||||
if( currentClock.tv_sec - m_timeLastRefreshRebalanceFhs.tv_sec > TIMEOUT_REBALANCE_LIST )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] rebalance list expired. %d sec.", TIMEOUT_REBALANCE_LIST );
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 저장된 list 정보가 존재하지 않는 경우... false 반환 처리
|
||||
if( m_listRebalanceFhs.size() <= 0 )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] rebalance list empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<std::string>::const_iterator it;
|
||||
std::list<std::string>::const_iterator itIgnore;
|
||||
std::string szHost;
|
||||
|
||||
pthread_mutex_lock( &m_mutexRebalanceFhs );
|
||||
|
||||
for( it = m_listRebalanceFhs.begin(); it != m_listRebalanceFhs.end(); ++it )
|
||||
{
|
||||
szHost = *it;
|
||||
|
||||
// 추출된 FHS 가 ignore list 에 존재하는지 확인
|
||||
itIgnore = std::find( listIgnoreFHS.begin(), listIgnoreFHS.end(), szHost );
|
||||
if( itIgnore == listIgnoreFHS.end() )
|
||||
{
|
||||
// ignore list 에 존재하지 않는 경우...
|
||||
// 해당 장비를 선택하고.. loop 종료 처리
|
||||
szResultHost = szHost;
|
||||
pthread_mutex_unlock( &m_mutexRebalanceFhs );
|
||||
|
||||
_LOG( LDBG, "[SHM INF] proper rebalance fhs [%s] selected.",szResultHost.c_str() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 적합한 장비를 찾지 못한 경우.
|
||||
pthread_mutex_unlock( &m_mutexRebalanceFhs );
|
||||
|
||||
_LOG( LDBG, "[SHM INF] proper rebalance fhs not selectd. total[%lu], ignore[%lu]."
|
||||
, m_listRebalanceFhs.size(), listIgnoreFHS.size() );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy content 를 저장할 target FHS 정보를 반환
|
||||
// 2021-01-07 NEW huibong 이동 대상 content 선택 관련 mode 기능 추가 (#33306)
|
||||
// - 복사 가능 FHS 가 존재하는지 검색 관련 오류 발생시 반환값 정보를 좀더 세분화 처리
|
||||
// - 정상 처리시 : return 1
|
||||
// - 복사 가능 물리적 FHS 가 없는 경우 : return -1
|
||||
// - 복사 가능 물리 FHS 는 존재하지만 ignore 목록에 포함되어.. 실제 복사 가능 FHS 가 없는 경우 : return 0
|
||||
int CShmInfoThread::GetCopyTargetFhs( std::string & szResultHost, std::list<std::string>& listIgnoreFHS )
|
||||
{
|
||||
// COPY 수신 가능 FHS list 에서
|
||||
// 전달받은 Ignore FHS 에 등록된 FHS 를 제외하고
|
||||
// 남은 FHS 중 맨 처음 나오는 정보를 전달한다.
|
||||
|
||||
// 1. 저장된 list 정보가 갱신이 되지 않아 오래된 경우.... 버린다.
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
|
||||
if( currentClock.tv_sec - m_timeLastRefreshCopyTargetFhs.tv_sec > TIMEOUT_COPY_LIST )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] copy target info list expired. %d sec.", TIMEOUT_COPY_LIST );
|
||||
|
||||
// 복사 가능 물리 FHS 가 아예 없는 경우... -1 return
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 2. 저장된 list 정보가 존재하지 않는 경우
|
||||
if( m_listCopyTargetFhs.size() <= 0 )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] ] copy target info list empty." );
|
||||
|
||||
// 복사 가능 물리 FHS 가 아예 없는 경우... -1 return
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
std::list<std::string>::const_iterator it;
|
||||
std::list<std::string>::const_iterator itIgnore;
|
||||
std::string szHost;
|
||||
|
||||
pthread_mutex_lock( &m_mutexCopyTargetFhs );
|
||||
|
||||
for( it = m_listCopyTargetFhs.begin(); it != m_listCopyTargetFhs.end(); ++it )
|
||||
{
|
||||
szHost = *it;
|
||||
|
||||
// 추출된 FHS 가 ignore list 에 존재하는지 확인
|
||||
itIgnore = std::find( listIgnoreFHS.begin(), listIgnoreFHS.end(), szHost );
|
||||
if( itIgnore == listIgnoreFHS.end() )
|
||||
{
|
||||
// ignore list 에 존재하지 않는 경우...
|
||||
// 해당 장비를 선택하고.. loop 종료 처리
|
||||
szResultHost = szHost;
|
||||
pthread_mutex_unlock( &m_mutexCopyTargetFhs );
|
||||
|
||||
_LOG( LDBG, "[SHM INF] proper copy target [%s] selected.", szResultHost.c_str() );
|
||||
|
||||
// 복사 가능 물리 FHS 가 존재하는 경우 ... 1 return
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 적합한 장비를 찾지 못한 경우.
|
||||
pthread_mutex_unlock( &m_mutexCopyTargetFhs );
|
||||
|
||||
LOG( LWAR, "[SHM INF] proper copy target fhs not selectd. total[%lu], ignore[%lu]."
|
||||
, m_listCopyTargetFhs.size(), listIgnoreFHS.size() );
|
||||
|
||||
// 복사 가능 물리 FHS 가 존재하지만.. ignore 에 포함되어.. 실제 가능 FHS 가 전혀 없는 경우 ... 0 return
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CShmInfoThread::IsValidCopyTargetFhs( void )
|
||||
{
|
||||
// 1. 저장된 list 정보가 갱신이 되지 않아 오래되었는지 check
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
|
||||
bool bResult = true;
|
||||
|
||||
pthread_mutex_lock( &m_mutexCopyTargetFhs );
|
||||
|
||||
if( currentClock.tv_sec - m_timeLastRefreshCopyTargetFhs.tv_sec > TIMEOUT_COPY_LIST )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] copy target list expired. %d sec.", TIMEOUT_COPY_LIST );
|
||||
bResult = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_listCopyTargetFhs.empty() == true )
|
||||
{
|
||||
LOG( LWAR, "[SHM INF] copy target list empty." );
|
||||
bResult = false;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &m_mutexCopyTargetFhs );
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
|
||||
void * CShmInfoThread::threadFunc( void * arg )
|
||||
{
|
||||
CShmInfoThread * pObject = reinterpret_cast<CShmInfoThread *>(arg);
|
||||
pthread_detach( pthread_self() );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
pthread_testcancel();
|
||||
pObject->Execute();
|
||||
pthread_testcancel();
|
||||
|
||||
// 지정된 주기로 실행
|
||||
sleep( pObject->m_uSleep );
|
||||
}
|
||||
|
||||
// thread 종료시 handle 정보 초기화
|
||||
pObject->m_threadHandle = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CShmInfoThread::Execute()
|
||||
{
|
||||
// 다음 sleep time 은 default 로 처리
|
||||
// - 하위 flow 에서 문제 발생하면 sleep time 을 max 로 조정
|
||||
m_uSleep = SLEEP_TIME_DEFAULT;
|
||||
|
||||
// rc_mond 가 기동 중인지 check
|
||||
// - 미기동 상태이면... 기동시까지 대기.
|
||||
if( IsRunRcMonD() == false )
|
||||
{
|
||||
m_uSleep = SLEEP_TIME_MAX;
|
||||
|
||||
_LOG( LERR, "[SHM INF] %s process not running. max sleep %u sec.", PROCESS_NAME_RC_MONITORING_DAEMON, m_uSleep );
|
||||
return;
|
||||
}
|
||||
|
||||
// 공유메모리 접근
|
||||
key_t iShmKey;
|
||||
|
||||
// 공유메모리 key 생성을 위한 임시 파일 생성 처리.
|
||||
FILE * pShmFile = fopen( RC_MOND_SHARED_MEMORY_KEY_FILE, "r" );
|
||||
|
||||
if( pShmFile == NULL )
|
||||
{
|
||||
// 공유메모리 접근 key file 존재하지 않는 경우....
|
||||
m_uSleep = SLEEP_TIME_MAX;
|
||||
|
||||
_LOG( LERR, "[SHM INF] %s shared memory key file(%s) not exist. max sleep %u sec."
|
||||
, PROCESS_NAME_RC_MONITORING_DAEMON , RC_MOND_SHARED_MEMORY_KEY_FILE , m_uSleep );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 공유메모리 접근 key file 존재하는 경우
|
||||
fclose( pShmFile );
|
||||
pShmFile = NULL;
|
||||
}
|
||||
|
||||
// 공유메모리 접근 key 값 추출
|
||||
iShmKey = ftok( RC_MOND_SHARED_MEMORY_KEY_FILE, 1 );
|
||||
if( iShmKey == (key_t)-1 )
|
||||
{
|
||||
// 공유메모리 접근 key 획득 실패시
|
||||
m_uSleep = SLEEP_TIME_MAX;
|
||||
|
||||
_LOG( LERR, "[SHM INF] %s shared memory key generate fail with file(%s). max sleep %u sec."
|
||||
, PROCESS_NAME_RC_MONITORING_DAEMON , RC_MOND_SHARED_MEMORY_KEY_FILE , m_uSleep );
|
||||
return;
|
||||
}
|
||||
|
||||
// 공유메모리 attach 처리
|
||||
CShmControl< struct RcInfo > shmCtl;
|
||||
if( shmCtl.Attach( iShmKey, sizeof( struct RcInfo ) ) == false )
|
||||
{
|
||||
// 공유메모리 접근 실패시
|
||||
m_uSleep = SLEEP_TIME_MAX;
|
||||
|
||||
_LOG( LERR, "[SHM INF] %s shared memory attach fail with key(%d). max sleep %u sec."
|
||||
, PROCESS_NAME_RC_MONITORING_DAEMON, iShmKey, m_uSleep );
|
||||
return;
|
||||
}
|
||||
|
||||
_LOG( LDBG, "[SHM INF] start." );
|
||||
|
||||
// 공유메모리 최상위 접근 포인터 획득
|
||||
struct RcInfo * pShm = shmCtl.GetShmPtr();
|
||||
|
||||
// copy 처리 수신 가능 FHS 추출 및 rebalance 대상 FHS 추출 목록 update
|
||||
if( RefreshFhsList( pShm ) == false )
|
||||
{
|
||||
// 실패 발생시 다음 sleep time 최대 설정.
|
||||
m_uSleep = SLEEP_TIME_MAX;
|
||||
}
|
||||
|
||||
// 공유메모리 접근 해제
|
||||
shmCtl.Detach();
|
||||
pShm = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool FhsScoreSortASC( const struct FhsScore & fhs1, const struct FhsScore & fhs2 )
|
||||
{
|
||||
return (fhs1.score < fhs2.score);
|
||||
}
|
||||
|
||||
bool FhsScoreSortDESC( const struct FhsScore & fhs1, const struct FhsScore & fhs2 )
|
||||
{
|
||||
return (fhs1.score > fhs2.score);
|
||||
}
|
||||
|
||||
|
||||
bool CShmInfoThread::RefreshFhsList( const struct RcInfo * const pShm )
|
||||
{
|
||||
// FHS 의 시스템 정보 업데이트가 오래된 경우..
|
||||
// - rc_mond 에서 지정된 시간( 20 sec ) 를 초과한 경우.. expire 처리하지만...
|
||||
// - 오류가 발생할 수 있고... FHS 상태가 이상할 경우.. 해당 장비는 선택하지 않는 것이 좋으므로...
|
||||
// - 업데이트가 비교적 최근에 발생한 FHS 정보만을 사용토록 한다.
|
||||
// - csagentd 는 4(service), 10(system) sec 마다 정보 전송...
|
||||
// - 따라서.. 8 sec 초과된 정보는 사용하지 않도록 한다.
|
||||
// - local time 은 시간 동기화 영향 받으므로... update_time_clock_sec 항목을 사용하여 판단한다.
|
||||
time_t expireTime;
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
expireTime = currentClock.tv_sec - 8;
|
||||
|
||||
|
||||
// 1. Write 가능 FHS 의 Storage 사용량 정보를 조회하여 평균을 구한다.
|
||||
// - 전체 FHS 의 평균을 구하면.. 용량이 충분한데 장비 문제로 강제 업로드 막은 장비까지 계산되어
|
||||
// - 평균을 낮추 버리는 문제가 발생하여...
|
||||
// - reblance 수신 FHS 가 다시 rebalance 처리 대상 FHS 가 될 수 있는 문제가 생긴다.
|
||||
const struct ClientInfo * pClient = NULL;
|
||||
unsigned int uFhsCount = 0;
|
||||
unsigned int uFhsTotalUsage = 0;
|
||||
int index = 0;
|
||||
unsigned int uFhsAverageUsage = 0;
|
||||
|
||||
for( index = 0; index <= pShm->client_max_index; index++ )
|
||||
{
|
||||
pClient = &(pShm->client[index]);
|
||||
|
||||
// slot 할당되어 있고.. data 가 유효하고..
|
||||
// write 가능 정상 상태 이고
|
||||
// system 상태 정보가 정상인 경우...( system 정보가 늦게 수신되므로.. 이를 반영 )
|
||||
// service 상태 정보가 expire 시간보다 오래되지 않은 최근 업데이트된 FHS 인 경우..
|
||||
if( pClient->use == 1
|
||||
&& pClient->valid == 1
|
||||
&& pClient->service.service_stat == SERVICE_STAT_OK
|
||||
&& pClient->system.update_time != 0
|
||||
&& pClient->service.update_time_clock_sec >= expireTime
|
||||
)
|
||||
{
|
||||
// 평균값 계산을 위한 값 처리
|
||||
uFhsTotalUsage += pClient->system.storage_max_usage;
|
||||
uFhsCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// write 가능 유효한 FHS 가 없는 경우
|
||||
if( uFhsCount < 1 )
|
||||
{
|
||||
_LOG( LWAR, "[SHM INF] starge average usage calc fail: write available fhs[%u] not exist.", uFhsCount );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Storage 사용량 평균값 계산
|
||||
uFhsAverageUsage = (uFhsTotalUsage / uFhsCount) + 1; // 소수점 짤려서.. 86.7% 여도 86 % 로 계산되므로.. 1 보정
|
||||
_LOG( LINF, "[SHM INF] starge average usage calc ok. write fhs count[%u], avg[%u %%]", uFhsCount, uFhsAverageUsage );
|
||||
|
||||
// 2. 평균 Storage 사용률 미만인 FHS 를 Copy 수신 FHS 로 선정한다.
|
||||
// - 만약 적합한 FHS 가 없는 경우 아래의 rebalance 대상 FHS 로 선정하지 않는다.
|
||||
if( RefreshCopyTargetFhsList( pShm, uFhsAverageUsage ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. rebalance 대상 FHS 로 선정한다.
|
||||
// - 평균 Storage 사용률이 70% 미만인 경우... 평균 Storage 사용률보다 3% 이상 높은 FHS 를 rebalance 대상 FHS 로 선정
|
||||
// - 평균 Storage 사용률이 70% 이상인 경우.. 평균 Storage 사용률보다 1% 이상 높은 FHS 를 rebalance 대상 FHS 로 설정
|
||||
unsigned int uRebalanceTargetStorageUsage = 0;
|
||||
if( uFhsAverageUsage < 70 )
|
||||
{
|
||||
uRebalanceTargetStorageUsage = uFhsAverageUsage + 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
uRebalanceTargetStorageUsage = uFhsAverageUsage + 1;
|
||||
}
|
||||
|
||||
if( RefreshRebalanceFhsList( pShm, uRebalanceTargetStorageUsage ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShmInfoThread::RefreshCopyTargetFhsList( const RcInfo * const pShm, unsigned int uStorageMaxUsage )
|
||||
{
|
||||
// FHS 의 시스템 정보 업데이트가 오래된 경우..
|
||||
// - rc_mond 에서 지정된 시간( 20 sec ) 를 초과한 경우.. expire 처리하지만...
|
||||
// - 오류가 발생할 수 있고... FHS 상태가 이상할 경우.. 해당 장비는 선택하지 않는 것이 좋으므로...
|
||||
// - 업데이트가 비교적 최근에 발생한 FHS 정보만을 사용토록 한다.
|
||||
// - csagentd 는 4(service), 10(system) sec 마다 정보 전송...
|
||||
// - 따라서.. 8 sec 초과된 정보는 사용하지 않도록 한다.
|
||||
// - local time 은 시간 동기화 영향 받으므로... update_time_clock_sec 항목을 사용하여 판단한다.
|
||||
time_t expireTime;
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
expireTime = currentClock.tv_sec - 8;
|
||||
|
||||
const struct ClientInfo * pClient = NULL;
|
||||
struct FhsScore stFhsScore;
|
||||
std::vector<struct FhsScore> vecFhsRank;
|
||||
int nFhsCount = 0;
|
||||
|
||||
vecFhsRank.clear();
|
||||
|
||||
// 2021-01-19 NEW huibong move 대상 FHS 선정시 disk busy 허용 max 값 추가 (#33395)
|
||||
// - conf 처리 관련 변수 사용하도록 수정 처리
|
||||
double dTargetFhsMaxDiskBusyLimit = CProcessConfig::GetInstance()->GetTargetFhsMaxDiskBusyLimit();
|
||||
|
||||
// write 가능 장비를 찾아.. score 계산.
|
||||
for( int i = 0; i <= pShm->client_max_index; i++ )
|
||||
{
|
||||
pClient = &(pShm->client[i]);
|
||||
|
||||
// slot 할당되어 있고.. data 가 유효하고..
|
||||
// write 가능 상태
|
||||
// system 상태 정보가 정상인 경우...( system 정보가 늦게 수신되므로.. 이를 반영 )
|
||||
// service 상태 정보가 expire 시간보다 오래되지 않은 최근 업데이트된 FHS 인 경우..
|
||||
// disk 최대 사용율이 평균값 미만
|
||||
// disk busy 하지 않고.. 남은 유효 용량 역시 충분한 경우
|
||||
if( pClient->use == 1
|
||||
&& pClient->valid == 1
|
||||
&& pClient->service.service_stat == SERVICE_STAT_OK
|
||||
&& pClient->system.update_time != 0
|
||||
&& pClient->service.update_time_clock_sec >= expireTime
|
||||
&& pClient->system.storage_max_usage < (int)uStorageMaxUsage
|
||||
&& pClient->system.disk_max_busy <= dTargetFhsMaxDiskBusyLimit
|
||||
&& pClient->system.storage_avail >= COPY_TARGET_DISK_MIN_AVAILABLE_LIMIT
|
||||
)
|
||||
{
|
||||
// 임시 객체 초기화.
|
||||
memset( &stFhsScore, 0x00, sizeof( struct FhsScore ) );
|
||||
|
||||
// hostname 저장.
|
||||
strncpy( stFhsScore.hostname, pClient->hostname, HOST_NAME_LENGTH );
|
||||
|
||||
// write score 계산 처리.
|
||||
// - storage_max_usage 항목과
|
||||
// - disk_max_busy * 전달받은 가중치 값의 합.
|
||||
stFhsScore.score = (double)(pClient->system.storage_max_usage)
|
||||
+ ((pClient->system.disk_max_busy) * COPY_TARGET_DISK_MAX_BUSY_WEIGHT);
|
||||
|
||||
// vector 에 결과 저장
|
||||
vecFhsRank.push_back( stFhsScore );
|
||||
|
||||
// count
|
||||
nFhsCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// copy write 가능 장비가 존재하면
|
||||
if( nFhsCount > 0 )
|
||||
{
|
||||
if( nFhsCount > 1 )
|
||||
{
|
||||
// 가장 점수가 낮아 이상적인 장비 순서로 정렬
|
||||
std::sort( vecFhsRank.begin(), vecFhsRank.end(), FhsScoreSortASC );
|
||||
}
|
||||
|
||||
// lock 을 걸고...
|
||||
// m_listCopyTargetFhs 정보 및 m_timeLastRefreshCopyTargetFhs 정보 업데이트.
|
||||
std::vector<struct FhsScore>::iterator it;
|
||||
std::string szRefresList;
|
||||
|
||||
// 기존 list 에 저장된 정보 clear
|
||||
pthread_mutex_lock( &m_mutexCopyTargetFhs );
|
||||
m_listCopyTargetFhs.clear();
|
||||
|
||||
for( it = vecFhsRank.begin(); it != vecFhsRank.end(); ++it )
|
||||
{
|
||||
// 정렬된 순서대로 list 에 push 처리
|
||||
m_listCopyTargetFhs.push_back( it->hostname );
|
||||
|
||||
szRefresList.append( it->hostname );
|
||||
szRefresList.append( " " );
|
||||
|
||||
_LOG( LDBG, "[SHM INF] copy target fhs list push_back.[%s].", it->hostname );
|
||||
}
|
||||
|
||||
// refresh time 정보 업데이트
|
||||
clock_gettime( CLOCK_MONOTONIC, &m_timeLastRefreshCopyTargetFhs );
|
||||
pthread_mutex_unlock( &m_mutexCopyTargetFhs );
|
||||
|
||||
_LOG( LINF, "[SHM INF] copy target fhs list refreshed. usage avg limit[%u %%]. [%d][%s]"
|
||||
, uStorageMaxUsage, nFhsCount, szRefresList.c_str() );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy 수신 가능 FHS 가 없는 경우...
|
||||
// - 관련 내역 로깅
|
||||
_LOG( LWAR, "[SHM INF] copy target fhs not exist. usage avg limit[%u %%], busy limit[%.1f %%]"
|
||||
, uStorageMaxUsage, dTargetFhsMaxDiskBusyLimit );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CShmInfoThread::RefreshRebalanceFhsList( const RcInfo * const pShm, unsigned int uStorageMinUsage )
|
||||
{
|
||||
// FHS 의 시스템 정보 업데이트가 오래된 경우..
|
||||
// - rc_mond 에서 지정된 시간( 20 sec ) 를 초과한 경우.. expire 처리하지만...
|
||||
// - 오류가 발생할 수 있고... FHS 상태가 이상할 경우.. 해당 장비는 선택하지 않는 것이 좋으므로...
|
||||
// - 업데이트가 비교적 최근에 발생한 FHS 정보만을 사용토록 한다.
|
||||
// - csagentd 는 4(service), 10(system) sec 마다 정보 전송...
|
||||
// - 따라서.. 8 sec 초과된 정보는 사용하지 않도록 한다.
|
||||
// - local time 은 시간 동기화 영향 받으므로... update_time_clock_sec 항목을 사용하여 판단한다.
|
||||
time_t expireTime;
|
||||
struct timespec currentClock;
|
||||
memset( ¤tClock, 0x00, sizeof( struct timespec ) );
|
||||
clock_gettime( CLOCK_MONOTONIC, ¤tClock );
|
||||
expireTime = currentClock.tv_sec - 8;
|
||||
|
||||
const struct ClientInfo * pClient = NULL;
|
||||
struct FhsScore stFhsScore;
|
||||
std::vector<struct FhsScore> vecFhsRank;
|
||||
int nFhsCount = 0;
|
||||
|
||||
vecFhsRank.clear();
|
||||
|
||||
// rebalance 대상 장비를 찾아.. score 계산.
|
||||
for( int i = 0; i <= pShm->client_max_index; i++ )
|
||||
{
|
||||
pClient = &(pShm->client[i]);
|
||||
|
||||
// slot 할당되어 있고.. data 가 유효하고..
|
||||
// read only 상태인 경우..
|
||||
// system 상태 정보가 정상인 경우...( system 정보가 늦게 수신되므로.. 이를 반영 )
|
||||
// service 상태 정보가 expire 시간보다 오래되지 않은 최근 업데이트된 FHS 인 경우..
|
||||
// disk 최대 사용율이 전달받은 값 이상이고
|
||||
// disk 최대 사용량이 REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT(%) 이상인 장비
|
||||
// disk busy 가 REBALANCE_TARGET_DISK_MAX_BUSY_LIMIT (%) 이하인 장비.
|
||||
if( pClient->use == 1
|
||||
&& pClient->valid == 1
|
||||
&& ( pClient->service.service_stat == SERVICE_STAT_RONLY || pClient->service.service_stat == SERVICE_STAT_OK )
|
||||
&& pClient->system.update_time != 0
|
||||
&& pClient->service.update_time_clock_sec >= expireTime
|
||||
&& pClient->system.storage_max_usage >= (int)uStorageMinUsage
|
||||
&& pClient->system.storage_max_usage >= REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT
|
||||
&& pClient->system.disk_max_busy <= REBALANCE_TARGET_DISK_MAX_BUSY_LIMIT )
|
||||
{
|
||||
|
||||
// 임시 객체 초기화.
|
||||
memset( &stFhsScore, 0x00, sizeof( struct FhsScore ) );
|
||||
|
||||
// hostname 저장.
|
||||
strncpy( stFhsScore.hostname, pClient->hostname, HOST_NAME_LENGTH );
|
||||
|
||||
// score 계산 처리.
|
||||
// - storage_max_usage 항목에서 disk_max_busy 값을 빼서 점수 계산
|
||||
stFhsScore.score = (double)(pClient->system.storage_max_usage)
|
||||
- ((pClient->system.disk_max_busy) * REBALANCE_TARGET_DISK_MAX_BUSY_WEIGHT);
|
||||
|
||||
// vector 에 결과 저장
|
||||
vecFhsRank.push_back( stFhsScore );
|
||||
|
||||
// result count 증가.
|
||||
nFhsCount += 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Rebalance 대상 장비가 존재하면
|
||||
if( nFhsCount > 0 )
|
||||
{
|
||||
if( nFhsCount > 1 )
|
||||
{
|
||||
// 가장 점수가 높은 순으로 정렬
|
||||
std::sort( vecFhsRank.begin(), vecFhsRank.end(), FhsScoreSortDESC );
|
||||
}
|
||||
|
||||
std::string szRefresList;
|
||||
|
||||
// lock 을 걸고...
|
||||
// m_listCopyTargetFhs 정보 및 m_timeLastRefreshCopyTargetFhs 정보 업데이트.
|
||||
std::vector<struct FhsScore>::iterator it;
|
||||
|
||||
// 기존 list 에 저장된 정보 clear
|
||||
pthread_mutex_lock( &m_mutexRebalanceFhs );
|
||||
m_listRebalanceFhs.clear();
|
||||
|
||||
for( it = vecFhsRank.begin(); it != vecFhsRank.end(); ++it )
|
||||
{
|
||||
// 정렬된 순서대로 list 에 push 처리
|
||||
m_listRebalanceFhs.push_back( it->hostname );
|
||||
|
||||
szRefresList.append( it->hostname );
|
||||
szRefresList.append( " " );
|
||||
|
||||
_LOG( LDBG, "[SHM INF] rebalance fhs list push_back.[%s]", it->hostname );
|
||||
}
|
||||
|
||||
// refresh time 정보 업데이트
|
||||
clock_gettime( CLOCK_MONOTONIC, &m_timeLastRefreshRebalanceFhs );
|
||||
pthread_mutex_unlock( &m_mutexRebalanceFhs );
|
||||
|
||||
_LOG( LINF, "[SHM INF] rebalance fhs list refreshed. usage limit[%u %%]. [%d][%s]"
|
||||
, (uStorageMinUsage > REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT ? uStorageMinUsage : REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT)
|
||||
, nFhsCount, szRefresList.c_str() );
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rebalance 처리 대상 FHS 가 없는 경우...
|
||||
// - 관련 내역 로깅
|
||||
_LOG( LINF, "[SHM INF] rebalance fhs not exist with usage limit [%u %%], busy limit [%.2f %%]"
|
||||
, (uStorageMinUsage > REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT ? uStorageMinUsage : REBALANCE_TARGET_DISK_MIN_USAGE_LIMIT)
|
||||
, REBALANCE_TARGET_DISK_MAX_BUSY_LIMIT );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user