base
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
#include "TrafficControlThread.h"
|
||||
#include "Logger.h"
|
||||
#include "ProcessConfig.h"
|
||||
#include "RcdbInfo.h"
|
||||
#include "Database.h"
|
||||
#include "ReportLog.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
|
||||
// 네트워크 통계 모듈의 sqlite SQLITE_BUSY 잦은 발생으로 INSERT 지연 발생 (#21440)
|
||||
// 이로 인해 Traffic 통계 합산이 정상적으로 처리되지 않을 수 있으므로 다음과 같이 조정 처리
|
||||
// - Timestamp delay 15 sec -> 16 sec 로 변경 처리 ( 기존 3.4 rc_statd 는 15 sec 였으나.. 신규 fimngd 적용에 따라 조정 처리)
|
||||
// - sqlite lock timeout 값을 3 sec -> 1 sec 로 변경 처리
|
||||
|
||||
#define TIMESTAMP_DELAY_SEC 16 // 5분단위 timestamp 변경시... 변경 후.. 어느만큼 delay 를 허용할지 시간값.
|
||||
#define SQLITE_DB_LOCK_TIMEOUT 1000 // 세션 중에 SQLITE_BUSY 상황 발생 문제 해결을 위해 DB Lock 관련 timeout 설정값. (1 sec)
|
||||
|
||||
|
||||
#define TRAFFIC_CONTROL_LOW_LIMIT 25 // 트래픽 제한 관련 전송률의 최소값(%), 해당값 이하로는 떨어지지 않도록 처리.
|
||||
#define REPORT_TRAFFIC_CONTROL_LIMIT 50 // 트래픽 제한 관련 전송률이 해당 값(%) 이하로 떨어질 경우.. report 로그에 기록 처리한다.
|
||||
|
||||
|
||||
// 생성자..
|
||||
CTrafficControlThread::CTrafficControlThread()
|
||||
{
|
||||
// Thread Handle 초기화
|
||||
m_threadHandle = 0;
|
||||
}
|
||||
|
||||
// 소멸자..
|
||||
CTrafficControlThread::~CTrafficControlThread()
|
||||
{
|
||||
// Thread 가 동작 중인 경우 Thread 동작 정지 처리.
|
||||
if( m_threadHandle != 0 )
|
||||
pthread_cancel(m_threadHandle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Thread 를 생성하여 작업을 시작한다...
|
||||
bool CTrafficControlThread::Start()
|
||||
{
|
||||
int nResult = pthread_create( &m_threadHandle, NULL, CTrafficControlThread::threadFunc, this );
|
||||
if( nResult != 0 )
|
||||
{
|
||||
// Thread 생성 실패시...
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "TrafficControlThread: Thread create failed.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Thread 함수...
|
||||
void * CTrafficControlThread::threadFunc( void * arg )
|
||||
{
|
||||
CTrafficControlThread * pObject = reinterpret_cast<CTrafficControlThread *>(arg);
|
||||
pthread_detach( pthread_self() );
|
||||
|
||||
// 초기 기동시...통계 정보 및 timestamp 처리 관련 문제로 인해....
|
||||
// 지정된 시간 sleep 했다가.. 작업을 시작한다.
|
||||
sleep( TIMESTAMP_DELAY_SEC );
|
||||
|
||||
// 본 Thread 에서는
|
||||
// RCDB t_sms_sp_svc_product_band 테이블에 저장된 서비스별 트래픽 제어 정보를 조회하여..
|
||||
// Local DB 에 저장된 서비스별 Network 통계 정보를 바탕으로... 현재 5분간 트래픽을 어느 수준으로 제어할 것인지 판단하여...
|
||||
// RCDB t_sms_sp_svc_product_band 테이블에 UPDATE 처리를 주기적으로 수행한다.
|
||||
// 실제 본 thread function 에서 loop 를 동작하는 것이 아니라....
|
||||
// 객체 execute 함수 내에서 loop 로 동작하도록 한다.
|
||||
|
||||
pthread_testcancel();
|
||||
pObject->Execute();
|
||||
pthread_testcancel();
|
||||
|
||||
// Thread 종료시 Handle 초기화
|
||||
pObject->m_threadHandle = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// RCDB t_sms_sp_svc_product_band 테이블에 저장된 서비스별 트래픽 제어 정보를 조회하여..
|
||||
// Local DB 에 저장된 Network 통계 정보와 계산을 통해.. 향후 5분간 서비스 트래픽을 어느수준으로 제어할 것인지 계산...
|
||||
// 해당 결과를 RCDB t_sms_sp_svc_product_band 테이블에 업데이트 처리한다.
|
||||
void CTrafficControlThread::Execute()
|
||||
{
|
||||
// 변수 선언 및 초기화..
|
||||
time_t currentTime; // 현재 시간 정보를 저장하기 위한 변수..
|
||||
|
||||
unsigned long nowTimestamp = 0; // 현재 시간 기준으로 계산된 timestamp;
|
||||
unsigned long delayTimestamp = 0; // 지정된 시간동안 delay 를 통해 보정 처리된 timestamp;
|
||||
|
||||
|
||||
// RCDB 접속 정보 저장 관련 객체 생성 및 초기화...
|
||||
CRcdbInfo rcdbInfo;
|
||||
rcdbInfo.Load();
|
||||
|
||||
// Local DB 관련 변수 초기화.
|
||||
sqlite3 * db = NULL;
|
||||
sqlite3_stmt * stmt = NULL;
|
||||
int db_result;
|
||||
int nRetryCount;
|
||||
|
||||
|
||||
const char * select_sql = "SELECT sum(down_traffic)*8/300 FROM network_stat WHERE timestamp = ? AND user_seq = ? AND svc_seq = ?";
|
||||
|
||||
|
||||
// RCDB 조회 결과를 저장하기 위한 임시 변수.
|
||||
struct traffic_control_info stTraffic;
|
||||
int nResult;
|
||||
|
||||
|
||||
// Logging
|
||||
_LOG( LINF, "TrafficControlThread: start...");
|
||||
|
||||
|
||||
// 주기적으로 Network 통계 정보를 바탕으로 RCDB 트래픽 제어 정보를 업데이트 한다.
|
||||
while( 1 )
|
||||
{
|
||||
|
||||
// FHS 는 장비의 시간을 기준으로.. timestamp 값이 변경 후 20 sec 후에... 트래픽 제한 정보를 refresh 처리한다.
|
||||
// 기존 rc_statd(3.4 이전) 는 대략 timestamp 변경 후 12 sec 후에 RCDB 에 트래픽 제한 정보를 업데이트 처리한다.
|
||||
// 따라서.. 본 loop 에서는 timestamp 값 변경 후 약 TIMESTAMP_DELAY_SEC sec 후에 RCDB 에 트래픽 제한 정보를 업데이트토록 처리한다.
|
||||
|
||||
// 1. 현재 시간 정보 추출..
|
||||
currentTime = time(0);
|
||||
|
||||
// 2. 현재 시간 정보를 기준으로 timestamp 값을 계산한다...
|
||||
// 계산시.. FHS 장비들이 시간 동기화 오차로... 통계 정보가 늦게 올라와 저장될 수 있으므로...
|
||||
// 위에서 언급한대로 TIMESTAMP_DELAY_SEC sec 보정 처리하여 5분 단위 timestamp 값을 추출한다.
|
||||
nowTimestamp = (currentTime + 299)/300;
|
||||
delayTimestamp = (currentTime - TIMESTAMP_DELAY_SEC + 299)/300;
|
||||
|
||||
|
||||
// 3. 현재 timestamp 와 보정 처리된 delayTimestamp 값이 동일한 경우....
|
||||
if( nowTimestamp == delayTimestamp )
|
||||
{
|
||||
// 1 sec 대기 후 timestamp 변경이 되었는지 다시 계산하도록 처리...
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nowTimestamp 와 delayTimestamp 는 5분단위 정각에 값이 변경되어 서로 값이 달라지므로....
|
||||
// 지정된 시간 동안 sleep 처리 후... 실제 작업을 수행한다.
|
||||
sleep( TIMESTAMP_DELAY_SEC );
|
||||
}
|
||||
|
||||
|
||||
_LOG( LINF, "TrafficControlThread: Traffic Control update job start. timestamp[%lu]", nowTimestamp );
|
||||
|
||||
// 이제 실제 작업을 수행한다.
|
||||
|
||||
// 1. RCDB 와 연결을 수행한다.
|
||||
// - RCDB 연결은 5분마다 발생하므로.. 세션을 유지하지 않고.. 필요할 경우에만 연결/연결해제 하도록 처리한다.
|
||||
DataBase rcdb;
|
||||
m_vecTraffic.clear();
|
||||
|
||||
|
||||
// RCDB 와 연결을 시도한다.
|
||||
if( rcdb.PgOpenDB( rcdbInfo.m_strRcdbIp, rcdbInfo.m_nRcdbPort, rcdbInfo.m_strRcdbName, rcdbInfo.m_strRcdbAcct, rcdbInfo.m_strRcdbAcctPw) == NULL )
|
||||
{
|
||||
// 연결 실패시... 5분 후 재시도하도록 한다.
|
||||
LOG( LERR, "TrafficControlThread: RCDB connection failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// RCDB 와 연결 성공시....
|
||||
// t_sms_sp_svc_product_band 테이블을 조회하여 트래픽 제어가 필요한 서비스 관련 정보를 추출, 멤버 변수에 저장한다.
|
||||
char szQuery[1024];
|
||||
|
||||
snprintf( szQuery, 1023,
|
||||
"SELECT A.sp_user_seq, A.sp_svc_tran_id, B.volume_bandwidth_limit, B.volume_bandwidth_current, B.volume_bandwidth_control_current "
|
||||
"FROM t_sms_sp_svc_product A, t_sms_sp_svc_product_band B "
|
||||
"WHERE A.sp_user_seq = B.sp_user_seq "
|
||||
" AND A.sp_svc_tran_id = B.sp_svc_tran_id "
|
||||
" AND A.bandwidth_ctrl_yn = 'Y'");
|
||||
|
||||
// 조회 Query 수행.
|
||||
rcdb.PgDoExec(szQuery);
|
||||
|
||||
// 수행 결과 확인
|
||||
if( rcdb.PgResult( DataBase::NOT_CLEAR ) < 0 )
|
||||
{
|
||||
// Query 수행 결과 오류 발생시...
|
||||
LOG( LERR, "TrafficControlThread: RCDB select query failed.[%s][%s]", rcdb.GetErrorMessage().c_str(), szQuery );
|
||||
}
|
||||
else
|
||||
{
|
||||
// query 수행이 정상인 경우.
|
||||
nResult = rcdb.GetNoTuples();
|
||||
|
||||
// 조회 결과를 멤버변수 vector 에 저장한다.
|
||||
for( int i = 0; i < nResult; i++ )
|
||||
{
|
||||
stTraffic.user_seq = atoi ( rcdb.GetValue( i, 0 ) );
|
||||
stTraffic.svc_seq = atoi ( rcdb.GetValue( i, 1 ) );
|
||||
stTraffic.limit = atoll( rcdb.GetValue( i, 2 ) );
|
||||
stTraffic.previous_traffic = atoll( rcdb.GetValue( i, 3 ) );
|
||||
stTraffic.previous_control_precent = atoi ( rcdb.GetValue( i, 4 ) );
|
||||
|
||||
// 나머지 변수도 초기화 처리
|
||||
stTraffic.current_traffic = 0; // Local db 조회시 정보가 없을 수 있으므로 0 으로 설정.
|
||||
stTraffic.current_control_precent = 10000; // Local db 조회시 정보가 없을 수 있으므로... 100 % 의미의 값을 default 로 설정.
|
||||
|
||||
// vector 에 push 처리
|
||||
m_vecTraffic.push_back( stTraffic );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// RCDB 조회 결과 set 를 clear 처리한다.
|
||||
rcdb.PgClear();
|
||||
|
||||
// 트래픽 제어 설정된 서비스가 존재하는 경우..
|
||||
if( m_vecTraffic.empty() == false )
|
||||
{
|
||||
// Local DB 에서 해당 서비스 및 timestamp 에 맞는 트래픽 정보를 추출한다.
|
||||
std::vector<struct traffic_control_info>::iterator it;
|
||||
|
||||
// Local DB 와 연결을 수행한다.
|
||||
db_result = sqlite3_open( CProcessConfig::GetInstance()->GetLocalDbFileName(), &db);
|
||||
if( db_result != SQLITE_OK )
|
||||
{
|
||||
LOG( LERR, "TrafficControlThread: sqlite3 open failed.[%s][%d][%s]", CProcessConfig::GetInstance()->GetLocalDbFileName(), db_result, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// DB File 이 open 된 경우...
|
||||
nRetryCount = 0;
|
||||
|
||||
// bind 관련 Query 를 수행할 stmt 객체 생성.
|
||||
// - 만약 sqlite DB File 이 사전에 생성되어 있지 않은 경우... 위의 open 함수에서 0 파일을 생성되어 정상적으로 open 처리되지만..
|
||||
// sqlite3_prepare 함수에서 table 이 생성되어 있지 않으므로 오류가 발생함.
|
||||
// 따라서 loop 중에 재시도하도록 한다.
|
||||
db_result = sqlite3_prepare(db, select_sql, strlen(select_sql), &stmt, NULL );
|
||||
|
||||
// sqlite3_prepare() 함수 실행시 SQLITE_BUSY 오류가 발생할 수 있으므로.. 재시도 로직을 추가한다.
|
||||
while( db_result == SQLITE_BUSY && nRetryCount < 30 )
|
||||
{
|
||||
// sqlite 에서 SQLITE_BUSY 반환 관련 lock 대기 timeout 을 설정.
|
||||
sqlite3_busy_timeout( db, SQLITE_DB_LOCK_TIMEOUT );
|
||||
++nRetryCount;
|
||||
|
||||
LOG( LWAR, "TrafficControlThread: sqlite3 prepare SQLITE_BUSY, Retry[%d]", nRetryCount );
|
||||
|
||||
db_result = sqlite3_prepare(db, select_sql, strlen(select_sql), &stmt, NULL );
|
||||
}
|
||||
|
||||
if( db_result != SQLITE_OK )
|
||||
{
|
||||
LOG( LERR, "TrafficControlThread: sqlite3 prepare failed.[%d][%s]", db_result, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
stmt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sqlite 접속이 정상적으로 된 경우...
|
||||
if( stmt != NULL )
|
||||
{
|
||||
// vector 에 저장된 서비스 정보에 맞는 트래픽 정보를 추출한다.
|
||||
for( it = m_vecTraffic.begin(); it != m_vecTraffic.end(); ++it )
|
||||
{
|
||||
/*
|
||||
_LOG( LDBG, "TrafficControlThread: RCDB result. svc[%d][%d] traffic[%llu/%llu] control[%u]"
|
||||
, it->user_seq, it->svc_seq, it->previous_traffic, it->limit, it->previous_control_precent );
|
||||
*/
|
||||
|
||||
sqlite3_bind_int64( stmt, 1, nowTimestamp-1 );
|
||||
sqlite3_bind_int ( stmt, 2, it->user_seq );
|
||||
sqlite3_bind_int ( stmt, 3, it->svc_seq );
|
||||
|
||||
// Query 수행
|
||||
db_result = sqlite3_step(stmt);
|
||||
nRetryCount = 0;
|
||||
|
||||
// 만약 BUSY 상태로 인해 오류가 발생하면..20번 재시도
|
||||
while( db_result == SQLITE_BUSY && nRetryCount < 15 )
|
||||
{
|
||||
sqlite3_busy_timeout( db, SQLITE_DB_LOCK_TIMEOUT );
|
||||
++nRetryCount;
|
||||
|
||||
LOG( LWAR, "TrafficControlThread: sqlite3 step SQLITE_BUSY, Retry[%d]",nRetryCount );
|
||||
|
||||
// query 재시도
|
||||
db_result = sqlite3_step(stmt);
|
||||
}
|
||||
|
||||
|
||||
// select 조회 결과가 존재하는 경우... SQLITE_ROW (100 ) 을 반환...
|
||||
// select 조회 결과가 없는 경우.. SQLITE_DONE (101) 을 반환.
|
||||
|
||||
// select query 수행시 오류가 발생한 경우...
|
||||
if( db_result != SQLITE_ROW && db_result != SQLITE_DONE )
|
||||
{
|
||||
LOG( LERR, "TrafficControlThread: sqlite3 step error.[%d][%s]", db_result, sqlite3_errmsg(db));
|
||||
|
||||
// 조회 loop 를 벗어나.. 마무리 작업을 한 후 다음 5분 후에 다시 시도하도록 한다.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// select 조회 결과가 존재하는 경우... 1개 Row 만 존재하므로...
|
||||
if( db_result == SQLITE_ROW )
|
||||
{
|
||||
it->current_traffic = sqlite3_column_int64(stmt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Query 수행된 경우.. prepared 문을 재사용하기 위해 reset 처리한다.
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
|
||||
|
||||
// Local DB 와의 연결을 종료 처리한다.
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
stmt = NULL;
|
||||
}
|
||||
|
||||
|
||||
// vector 에 수집된 정보를 바탕으로
|
||||
// 계산을 통해 현재 5분간 트래픽을 어느 수준을 제어할지 결정한다.
|
||||
for( it = m_vecTraffic.begin(); it != m_vecTraffic.end(); ++it )
|
||||
{
|
||||
// 기본 조건
|
||||
// 1. 제한값이 0 인 경우.. 전송률은 0.01% (1) 로 설정한다.
|
||||
// 2. 트래픽 전송율은 서비스 품질을 위해 최대 25% 수준까지만 제한한다.
|
||||
// - 일반적으로 50% 이하로 제한되면...트래픽 증설을 권고할 수 있도록... report 로그에 기록 처리.
|
||||
// 3. 트래픽 전송율은 감소시킬 경우... Slow 하게... 원복시킬 경우에는 Fast 하게 처리될 수 있도록 한다.
|
||||
|
||||
|
||||
// 제한값이 0인 경우.. -> 운영자가 트래픽을 0으로 제한해 버린 경우...
|
||||
if( it->limit == 0 )
|
||||
{
|
||||
it->current_control_precent = 1; // 0.01 % 로 설정 처리.
|
||||
}
|
||||
else
|
||||
{
|
||||
// limit 값이 0 을 초과하는 경우...
|
||||
|
||||
// 현재 트래픽이 0 인 경우.. 전송율은 default 100% 로 설정처리.
|
||||
// - 해당 사항은 실제 traffic 전송한 것이 없거나....
|
||||
// - local db 조회 결과가 존재하지 않는 경우에 발생한다.
|
||||
if( it->current_traffic == 0 )
|
||||
{
|
||||
it->current_control_precent = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 현재 트래픽이 존재하는 경우....
|
||||
|
||||
if( it->current_traffic > it->limit )
|
||||
{
|
||||
// 현재 트래픽이... 제한 트래픽을 초과한 경우...
|
||||
// - 초과된 비율을 계산한 후..
|
||||
// - 기존 비율에서 초과된 비율만큼 감소시키되.. 최대 20% 로 제한.
|
||||
unsigned int nOverPercent = (it->current_traffic - it->limit ) * 10000 / it->limit ;
|
||||
|
||||
if( nOverPercent > 2000 )
|
||||
it->current_control_precent = it->previous_control_precent - 2000;
|
||||
else
|
||||
it->current_control_precent = it->previous_control_precent - nOverPercent;
|
||||
|
||||
}
|
||||
else if( it->current_traffic < it->limit )
|
||||
{
|
||||
// 현재 트래픽이 제한 트래픽을 초과하지 않은 경우...
|
||||
// - 현재 트래픽이 제한 트래픽의 90% 초과 수준인 경우에는 현재 제한율 유지...
|
||||
// - 현재 트래픽이 제한 트래픽의 90% 이하인 경우...10 % 씩 증설 처리 ( 최대 100 % )
|
||||
|
||||
unsigned int nUsedPercent = it->current_traffic * 10000 / it->limit;
|
||||
|
||||
if( nUsedPercent > 9000 )
|
||||
it->current_control_precent = it->previous_control_precent;
|
||||
else
|
||||
it->current_control_precent = it->previous_control_precent + 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 제한 트래픽과 현재 트래픽이 동일한 경우...
|
||||
// 기존 전송율을 유지.
|
||||
it->current_control_precent = it->previous_control_precent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 마지막으로 전송율 최소값 25%, 최대값 100% 이상을 초과하는 경우.. 보정 처리한다.
|
||||
if( it->current_control_precent < (TRAFFIC_CONTROL_LOW_LIMIT * 100) )
|
||||
{
|
||||
it->current_control_precent = (TRAFFIC_CONTROL_LOW_LIMIT * 100);
|
||||
}
|
||||
else if( it->current_control_precent > 10000 )
|
||||
{
|
||||
it->current_control_precent = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 전송율이 50% 미만으로 떨어질 경우.... report log 에 기록하여.. 운영자가 확인할 수 있도록 한다.
|
||||
if( it->limit > 0 && it->current_control_precent < (REPORT_TRAFFIC_CONTROL_LIMIT * 100) )
|
||||
{
|
||||
_LOG( LWAR, "TrafficControlThread: service traffic control value set below %d%%. svc[%d][%d] limit[%llu] traffic[%llu->%llu] control[%5.2f->%5.2f%%]"
|
||||
, REPORT_TRAFFIC_CONTROL_LIMIT, it->user_seq, it->svc_seq, it->limit
|
||||
, it->previous_traffic, it->current_traffic, it->previous_control_precent/100.0, it->current_control_precent/100.0 );
|
||||
|
||||
// report 로그에 해당 내역 기록 처리...
|
||||
CReportLog reportLog;
|
||||
std::string strErrorMessage;
|
||||
strErrorMessage.clear();
|
||||
|
||||
if( reportLog.Init( CProcessConfig::GetInstance()->GetLogPath() ) == false )
|
||||
{
|
||||
reportLog.GetLastError( strErrorMessage );
|
||||
LOG( LERR, "TrafficControlThread: report log init failed.[%s]", strErrorMessage.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
reportLog.Write( "WAR", "[%s][service traffic control value set below %d%%. svc[%d][%d] limit[%llu] traffic[%llu->%llu] control[%5.2f->%5.2f%%]]"
|
||||
, PROG_NAME, REPORT_TRAFFIC_CONTROL_LIMIT
|
||||
, it->user_seq, it->svc_seq, it->limit
|
||||
, it->previous_traffic, it->current_traffic, it->previous_control_precent/100.0, it->current_control_precent/100.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vector 에 저장된 최종 트래픽 제어 정보를 RCDB 에 UPDATE 처리한다.
|
||||
for( it = m_vecTraffic.begin(); it != m_vecTraffic.end(); ++it )
|
||||
{
|
||||
snprintf( szQuery, 1023,
|
||||
"UPDATE t_sms_sp_svc_product_band "
|
||||
"SET "
|
||||
" volume_bandwidth_current = '%llu' "
|
||||
" , volume_bandwidth_before = '%llu' "
|
||||
" , volume_bandwidth_control_current = '%u' "
|
||||
" , volume_bandwidth_control_before = '%u' "
|
||||
" , volume_bandwidth_update_datetime = now() "
|
||||
"WHERE sp_user_seq = %d AND sp_svc_tran_id = %d "
|
||||
, it->current_traffic, it->previous_traffic, it->current_control_precent, it->previous_control_precent
|
||||
, it->user_seq, it->svc_seq );
|
||||
|
||||
|
||||
// update query 수행.
|
||||
rcdb.PgDoExec(szQuery);
|
||||
|
||||
// update 실패 발생시...
|
||||
if( rcdb.GetCmdTuples() <= 0 )
|
||||
{
|
||||
LOG( LERR, "TrafficControlThread: RCDB update query failed.[%s][%s]", rcdb.GetErrorMessage().c_str(), szQuery);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
_LOG( LINF, "TrafficControlThread: RCDB update OK..svc[%d][%d] limit[%llu] traffic[%llu->%llu] control[%5.2f->%5.2f%%]"
|
||||
, it->user_seq, it->svc_seq, it->limit
|
||||
, it->previous_traffic, it->current_traffic, it->previous_control_precent/100.0, it->current_control_precent/100.0 );
|
||||
}
|
||||
|
||||
// Update 처리 정상 수행시... RCDB 결과 Set 을 Clear 처리한다.
|
||||
rcdb.PgClear();
|
||||
}
|
||||
|
||||
|
||||
}// RCDB 조회 결과가 존재하는 경우...
|
||||
|
||||
|
||||
// RCDB 관련 종료 처리 작업 수행.
|
||||
rcdb.PgCloseDB();
|
||||
}
|
||||
|
||||
|
||||
// 작업 완료 후.. 불필요하게 loop 를 동작시킬 필요가 없고.. timestamp 체크 관련 루프 계산 문제로 인해서...
|
||||
// 5분 단위로 동작해야 하므로... 약 3분 정도 sleep 한다.
|
||||
sleep(180);
|
||||
}
|
||||
|
||||
|
||||
// 종료 처리 코드
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user