base
This commit is contained in:
@@ -0,0 +1,415 @@
|
||||
#include "ArecaWrapper.h"
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#define MAX_EVENT_BUFF_SIZE 512
|
||||
|
||||
#define UNKNOWN_EVT_STR "Unknown Event"
|
||||
|
||||
|
||||
CArecaWrapper::CArecaWrapper(int nEventLevel)
|
||||
: m_nEventLevel( nEventLevel )
|
||||
{
|
||||
pthread_mutex_init(&mutex_lock, NULL);
|
||||
}
|
||||
|
||||
CArecaWrapper::~CArecaWrapper()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex_lock);
|
||||
int nInterfaceIndex;
|
||||
CArclib *ctrl;
|
||||
for (nInterfaceIndex =0; nInterfaceIndex < m_nTotalCtrl; nInterfaceIndex++)
|
||||
{
|
||||
ctrl = &m_Arc[nInterfaceIndex];
|
||||
LinuxIoctlInterface *out = (LinuxIoctlInterface*)ctrl->ArcGetInterface();
|
||||
delete out;
|
||||
}
|
||||
}
|
||||
|
||||
// libacrlib에서 사용하는 pSYS_TIME 타입의 값을 time_t로 변환한다.
|
||||
time_t CArecaWrapper::GetTime_t(pSYS_TIME evtTime)
|
||||
{
|
||||
/*
|
||||
tm tmpTime;
|
||||
|
||||
tmpTime.tm_year = evtTime->u.tmYear+100;
|
||||
tmpTime.tm_mon = evtTime->u.tmMonth-1;
|
||||
tmpTime.tm_mday = evtTime->u.tmDate;
|
||||
tmpTime.tm_hour = evtTime->u.tmHour;
|
||||
tmpTime.tm_min = evtTime->u.tmMinute;
|
||||
tmpTime.tm_sec = evtTime->u.tmSecond;
|
||||
|
||||
return mktime(&tmpTime);
|
||||
*/
|
||||
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
time ( &rawtime );
|
||||
timeinfo = gmtime ( &rawtime );
|
||||
|
||||
timeinfo->tm_year = evtTime->u.tmYear+100;
|
||||
timeinfo->tm_mon = evtTime->u.tmMonth-1;
|
||||
timeinfo->tm_mday = evtTime->u.tmDate;
|
||||
timeinfo->tm_hour = evtTime->u.tmHour;
|
||||
timeinfo->tm_min = evtTime->u.tmMinute;
|
||||
timeinfo->tm_sec = evtTime->u.tmSecond;
|
||||
timeinfo->tm_isdst = 0; // disable daylight saving time
|
||||
|
||||
time_t ret = mktime ( timeinfo );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CArecaWrapper::DisableUpload()
|
||||
{
|
||||
system( "touch /user/service/vmasd.disable" );
|
||||
|
||||
struct stat st;
|
||||
|
||||
if( lstat( "/user/service/vmasd.disable", &st ) != 0 )
|
||||
{
|
||||
ERROR_LOG( "can't touch vmasd.disable" );
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
INFO_LOG( "disable upload." );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CArecaWrapper::IsDisableUpload( int eventCategory, int eventId )
|
||||
{
|
||||
switch( eventCategory )
|
||||
{
|
||||
case EVENT_DEVICE: // device event
|
||||
/// The meaning of eventId
|
||||
/// 0 : Device Inserted
|
||||
/// 1 : Device Removed
|
||||
/// 2 : Reading Error
|
||||
/// 3 : Writing Error
|
||||
/// 4 : ATA Ecc Error
|
||||
/// 5 : Change ATA Mode
|
||||
/// 6 : Time Out Error
|
||||
/// 7 : Device Failed
|
||||
/// 8 : PCI Parity Error
|
||||
/// 9 : Dev Fail (SMART)
|
||||
/// 10 : Pass
|
||||
|
||||
|
||||
case EVENT_VOLUMESET: // volumeset event
|
||||
case EVENT_RAIDSET: // raidset event
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//int CArecaWrapper::GetEvent(int nEventFlag, char *pszResult)
|
||||
bool CArecaWrapper::GetEvent(int nEventFlag, list<CEventData>& listRet)
|
||||
{
|
||||
CArclib *ctrl;
|
||||
ARC_STATUS stat = ARC_SUCCESS;
|
||||
bool gotEvent = false;
|
||||
int nCount = 0; // total number of event objects we got
|
||||
int i;
|
||||
int nCurEvtLevel = EVT_SERIOUS;
|
||||
sSYSTEM_INFO sysInfo;
|
||||
BYTE ptr1[64];
|
||||
char tmpStr[64];
|
||||
char eventStrBuf[MAX_EVENT_BUFF_SIZE];
|
||||
int eventCategory = 0;
|
||||
int eventId = 0;
|
||||
|
||||
//the time event occurred, defined in arclib.h
|
||||
pSYS_TIME evtTime = (pSYS_TIME)new sSYS_TIME;
|
||||
|
||||
pthread_mutex_lock(&mutex_lock);
|
||||
if (m_nTotalCtrl == 0) {
|
||||
LOG(LERR, "No Raild controller was found.");
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
if( evtTime )
|
||||
{
|
||||
delete evtTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ctrl = &m_Arc[0];
|
||||
|
||||
memset(ptr1, 0, sizeof(ptr1));
|
||||
memset(tmpStr, 0, sizeof(tmpStr));
|
||||
memset(eventStrBuf, 0, sizeof(eventStrBuf));
|
||||
|
||||
// event object defined in arclib.h
|
||||
pEVENT_DATA pEventObject = (pEVENT_DATA)new sEVENT_DATA;
|
||||
stat = ctrl->ArcGetSysInfo(&sysInfo);
|
||||
if( stat != ARC_SUCCESS )
|
||||
{
|
||||
LOG(LERR, "ArcGetSysInfo Failed: %d",stat);
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
if( pEventObject )
|
||||
{
|
||||
delete pEventObject;
|
||||
}
|
||||
if( evtTime )
|
||||
{
|
||||
delete evtTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* We should call ArcSetTime() to correct the raid-subsystem time
|
||||
Call ArcGetReqEventPage() to get the required event page from raid subsystem.
|
||||
There are 4 event pages reside in the raid subsystem and each contains 16 event objects.
|
||||
*/
|
||||
memset(pEventObject, 0, sizeof(sEVENT_DATA));
|
||||
stat = ctrl->ArcGetReqEventPage(nEventFlag, &nCount);
|
||||
if (stat == ARC_SUCCESS)
|
||||
{
|
||||
if (nCount != 0)
|
||||
{
|
||||
for ( i = nCount - 1; i >= 0; i--)
|
||||
{
|
||||
// Call ArcGetEventObject function to extract the individual event object from event page
|
||||
if (ctrl->ArcGetEventObject( i, pEventObject ))
|
||||
{
|
||||
::memset(eventStrBuf, 0, MAX_EVENT_BUFF_SIZE);
|
||||
eventCategory = (int)pEventObject->evtCategory;
|
||||
eventId = pEventObject->evtType;
|
||||
|
||||
*((LONG *)evtTime) = pEventObject->evtTime;
|
||||
// Parse the event object we got
|
||||
switch ((int)pEventObject->evtCategory)
|
||||
{
|
||||
/*
|
||||
The member "evtStr" of event object structure contains the string to indicate
|
||||
which raidset owns this event object
|
||||
*/
|
||||
case EVENT_RAIDSET: // raidset event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( nCurEvtLevel > RS_EVT_NO_EVENT )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmRaidEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s",1, tmpStr, ptr1);
|
||||
gotEvent = true;
|
||||
break;
|
||||
/*
|
||||
The member "evtStr" of event object structure contains the string to indicate
|
||||
which volumeset owns this event object
|
||||
*/
|
||||
case EVENT_VOLUMESET: // volumeset event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( nCurEvtLevel >= VS_EVT_TOTALS)
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmVolEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1, tmpStr, ptr1);
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_DEVICE: // device event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
if( sysInfo.gsiTargetType == TARGET_SAS )
|
||||
{
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tmpStr, "IDE Channel #%2d", pEventObject->evtChannel + 1);
|
||||
}
|
||||
|
||||
if ( nCurEvtLevel >= DEV_EVT_TOTALS)
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmDevEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_HOST: // host event
|
||||
//this is Host SCSI events
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
if ( sysInfo.gsiScsiHostChannels)
|
||||
{
|
||||
if ( nCurEvtLevel >= SCSI_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmScsiHostEvent[pEventObject->evtType]);
|
||||
}
|
||||
} else {
|
||||
if ( nCurEvtLevel >= SCSI_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmIdeHostEvent[pEventObject->evtType]);
|
||||
}
|
||||
}
|
||||
|
||||
// CHG 2020-10-05 huibong FreeBSD 12.x 컴파일시 발생하는 warning 코드 수정 (#33225)
|
||||
// - FreeBSD 12.x 의 gcc 9.3 컴파일시 sprintf 사용 관련 buffer size 문제로 warning 발생
|
||||
// - flow 상으로는 buffer overflow 발생 가능성 없음
|
||||
// - 하지만.. 컴파일시마다 warning 발생하므로.. 수정 결정
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1, eventCat[pEventObject->evtCategory], ptr1 );
|
||||
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_HW_MONITOR: // hardware monitor event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, eventCat[pEventObject->evtCategory], 16);
|
||||
if ( nCurEvtLevel >= HW_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmHwMonEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_NEW_83782D:
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( pEventObject->evtType >= GHM_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmNewEventStr[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s",1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
case EVENT_NO_EVENT:
|
||||
// 이벤트가 없는 경우
|
||||
gotEvent = true;
|
||||
default:
|
||||
continue;
|
||||
}// end switch
|
||||
|
||||
}// end if
|
||||
|
||||
// 모든 이벤트를 결과 list에 추가필요 수정 2015-06-26
|
||||
CEventData objEvent;
|
||||
|
||||
objEvent.m_evtTime = GetTime_t(evtTime);
|
||||
objEvent.m_szEventData = eventStrBuf;
|
||||
objEvent.SetEventType( eventCategory, eventId );
|
||||
|
||||
listRet.push_back(objEvent);
|
||||
|
||||
|
||||
}// end for
|
||||
} else {
|
||||
_LOG(LWAR, "Event empty.");
|
||||
gotEvent = true;
|
||||
}
|
||||
}// end if
|
||||
|
||||
|
||||
if (pEventObject) {
|
||||
delete pEventObject;
|
||||
}
|
||||
|
||||
if (evtTime) {
|
||||
delete evtTime;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
return gotEvent;
|
||||
}
|
||||
|
||||
int CArecaWrapper::DiscoveryDevice(void)
|
||||
{
|
||||
dev_t dev;
|
||||
char buf[64];
|
||||
mode_t mode = 0666;
|
||||
unsigned int nTotalCtrl = 0;
|
||||
ARC_STATUS stat = ARC_SUCCESS;
|
||||
sSYSTEM_INFO sysInfo;
|
||||
|
||||
mode |= S_IFCHR;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sprintf(buf,"/dev/arcmsr%d", i);
|
||||
unlink(buf);
|
||||
}
|
||||
|
||||
for (int mymajor = 255; mymajor > 161; mymajor--)
|
||||
{
|
||||
for (int myminor = 0; myminor < 4; myminor++)
|
||||
{
|
||||
LinuxIoctlInterface *out = new LinuxIoctlInterface();
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sprintf(buf,"/dev/arcmsr%d", nTotalCtrl);
|
||||
dev = makedev(mymajor, myminor);
|
||||
mknod(buf, mode, dev);
|
||||
if (out->init(nTotalCtrl)) {
|
||||
stat = m_Arc[nTotalCtrl++].ArcInitSession(out);
|
||||
if (stat != ARC_SUCCESS) {
|
||||
_LOG(LERR, "ArcInitSession Failed : %d",stat);
|
||||
if( out )
|
||||
{
|
||||
delete out;
|
||||
out = NULL;
|
||||
}
|
||||
unlink(buf);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
delete out;
|
||||
out = NULL;
|
||||
unlink(buf);
|
||||
}
|
||||
}
|
||||
if (nTotalCtrl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nTotalCtrl;
|
||||
}
|
||||
|
||||
int CArecaWrapper::InitArecaControllers(void)
|
||||
{
|
||||
int nCount = 0;
|
||||
int nInterfaceIndex = 0;
|
||||
m_nTotalCtrl = DiscoveryDevice();
|
||||
_LOG(LDBG, "Total Count: %d", m_nTotalCtrl);
|
||||
|
||||
if(m_nTotalCtrl == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (nInterfaceIndex =0; nInterfaceIndex < m_nTotalCtrl; nInterfaceIndex++)
|
||||
{
|
||||
m_Arc[nInterfaceIndex].ArcGetReqEventPage(FLAG_ALL, &nCount);
|
||||
}
|
||||
|
||||
return m_nTotalCtrl;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************************************
|
||||
Areca Wrapper Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/19
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __ARECA_WRAPPER__
|
||||
#define __ARECA_WRAPPER__
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// 가장 중요하고 핵심적인 헤더 파일
|
||||
#include "arclib.h"
|
||||
#include "ethernet.h"
|
||||
#include "EventData.h"
|
||||
#include <list>
|
||||
#include "Logger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 필요한 인터페이스에 대한 헤더파일
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#include "linux_comm.h"
|
||||
#include "linux_ioctl.h"
|
||||
#if defined(__linux__)
|
||||
#include "linux_scsi.h"
|
||||
#include "linux_pass_ioctl.h"
|
||||
#else
|
||||
#include "freebsd_scsi.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 정보를 조회할 최대 컨트롤 수.
|
||||
#define MAX_CONTROLLER_SUPPORTED 64
|
||||
|
||||
// for GetEvent()'s first param
|
||||
#define GET_EVENT_ALL 0
|
||||
#define GET_EVENT_ONE 1
|
||||
|
||||
class CArecaWrapper
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief 생성자.
|
||||
/// @param nEventLevel [in] 필터 할 이벤트 레벨을 지정한다. conf를 통해 받아오게 되며, 레벨은 아래와 같다.
|
||||
///< -------- EVENT LEVEL ---------
|
||||
///< 0: Not to report
|
||||
///< 1: Serious Error Notification
|
||||
///< 2: Error Notification
|
||||
///< 3: Warning Notification
|
||||
///< 4: Information Notification
|
||||
///< ------------------------------
|
||||
CArecaWrapper(int nEventLevel);
|
||||
|
||||
/// @brief 소멸자.
|
||||
~CArecaWrapper();
|
||||
|
||||
/// @brief Areca Controller의 정보를 얻을 준비를 한다.
|
||||
// @return Areca Controller의 개수를 리턴한다. 없을 경우 -1을 리턴한다.
|
||||
int InitArecaControllers(void);
|
||||
|
||||
|
||||
/// @brief Areca Controller의 정보를 얻을 준비를 한다.
|
||||
/// @param nFlag [in] 이벤트 받을 형태를 지정한다.
|
||||
//< GET_EVENT_ALL : 저장된 모든 이벤트 데이터를 수신한다.
|
||||
//< GET_EVENT_ONE : 최근 1개의 이벤트 데이터를 수신한다.
|
||||
/// @param listRet [out] Areca Library를 통해 얻은 데이터를 저장한다. 데이터의 타입은 CEventData 형태이다.
|
||||
/// @return 성공시 true, 실패시 false 를 리턴한다.
|
||||
bool GetEvent(int nFlag, list<CEventData>& listRet);
|
||||
|
||||
private:
|
||||
CArclib m_Arc[MAX_CONTROLLER_SUPPORTED];
|
||||
|
||||
pthread_mutex_t mutex_lock;
|
||||
|
||||
int DiscoveryDevice(void);
|
||||
time_t GetTime_t(pSYS_TIME evtTime);
|
||||
int m_nEventLevel;
|
||||
int m_nTotalCtrl;
|
||||
|
||||
//bool IsDisableUpload( int eventCategory, int eventId );
|
||||
//bool DisableUpload();
|
||||
};
|
||||
#endif // __ARECA_WRAPPER__
|
||||
@@ -0,0 +1,127 @@
|
||||
/***************************************************************************
|
||||
AutoDisableUpload.cpp
|
||||
-----------------------------------------
|
||||
begin : 2011/07/26
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#include "AutoDisableUpload.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
CAutoDisableUpload::CAutoDisableUpload()
|
||||
{
|
||||
}
|
||||
|
||||
CAutoDisableUpload::~CAutoDisableUpload()
|
||||
{
|
||||
}
|
||||
|
||||
void CAutoDisableUpload::DoProcess( int eventCategory, int eventId )
|
||||
{
|
||||
if( IsDisableUpload( eventCategory, eventId ) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
system( "touch /user/service/vmasd.disable" );
|
||||
|
||||
struct stat st;
|
||||
|
||||
if( lstat( "/user/service/vmasd.disable", &st ) != 0 )
|
||||
{
|
||||
LOG(LERR, "can't touch vmasd.disable. event category = %s, event name = %s",
|
||||
m_szEventCategory.c_str(), m_szEventName.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
_LOG(LINF, "disable upload. event category = %s, event name = %s",
|
||||
m_szEventCategory.c_str(), m_szEventName.c_str() );
|
||||
}
|
||||
|
||||
bool CAutoDisableUpload::IsDisableUpload( int eventCategory, int eventId )
|
||||
{
|
||||
switch( eventCategory )
|
||||
{
|
||||
case EVENT_DEVICE:
|
||||
/// The meaning of eventId.
|
||||
/// 0(DEV_EVT_ADDED) - Device Inserted
|
||||
/// 1(DEV_EVT_REMOVED) - Device Removed
|
||||
/// 2(DEV_EVT_READ_ERROR) - Reading Error
|
||||
/// 3(DEV_EVT_WRITE_ERROR) - Writing Error
|
||||
/// 4(DEV_EVT_ATA_ECC_ERROR) - ATA Ecc Error
|
||||
/// 5(DEV_EVT_ATA_CHANGE_MODE) - Change ATA Mode
|
||||
/// 6(DEV_EVT_TIMEOUT) - Time Out Error
|
||||
/// 7(DEV_EVT_MARK_FAILED) - Device Failed
|
||||
/// 8(DEV_EVT_PCI_ERROR) - PCI Parity Error
|
||||
/// 9(DEV_EVT_SMART_FAILED) - Dev Fail (SMART)
|
||||
/// 10(DEV_EVT_CREATE_PASS) - Pass Through Disk Created
|
||||
/// 11(DEV_EVT_MODIFY_PASS) - Pass Through Disk Modified
|
||||
/// 12(DEV_EVT_DELETE_PASS) - Pass Through Disk Deleted
|
||||
|
||||
m_szEventCategory = "Device Event";
|
||||
m_szEventName = htmDevEvent[ eventId ];
|
||||
return ( eventId == DEV_EVT_MARK_FAILED ? true : false );
|
||||
|
||||
case EVENT_VOLUMESET:
|
||||
/// The meaning of eventId.
|
||||
/// 0(VS_EVT_INITIALIZING) - Start Initialize
|
||||
/// 1(VS_EVT_REBUILDING) - Start Rebuilding
|
||||
/// 2(VS_EVT_MIGRATING) - Start Migrating
|
||||
/// 3(VS_EVT_CHECKING) - Start Checking
|
||||
/// 4(VS_EVT_COMPLETE_INIT) - Complete Init
|
||||
/// 5(VS_EVT_COMPLETE_REBUILD) - Complete Rebuild
|
||||
/// 6(VS_EVT_COMPLETE_MIGRATING) - Complete Migrate
|
||||
/// 7(VS_EVT_COMPLETE_CHECKING) - Complete Check
|
||||
/// 8(VS_EVT_CREATE) - Create Volume
|
||||
/// 9(VS_EVT_DELETE) - Delete Volume
|
||||
/// 10(VS_EVT_MODIFY) - Modify Volume
|
||||
/// 11(VS_EVT_DEGRADED) - Volume Degraded
|
||||
/// 12(VS_EVT_FAILED) - Volume Failed
|
||||
/// 13(VS_EVT_REVIVED) - Failed Volume Revived
|
||||
/// 14(VS_EVT_ABORT_INIT) - Abort Initialization
|
||||
/// 15(VS_EVT_ABORT_REBUILD) - Abort Rebuilding
|
||||
/// 16(VS_EVT_ABORT_MIGRATING) - Abort Migration
|
||||
/// 17(VS_EVT_ABORT_CHECKING) - Abort Checking
|
||||
/// 18(VS_EVT_STOP_INIT) - Stop Initialization
|
||||
/// 19(VS_EVT_STOP_REBUILD) - Stop Rebuilding
|
||||
/// 20(VS_EVT_STOP_MIGRATING) - Stop Migration
|
||||
/// 21(VS_EVT_STOP_CHECKING) - Stop Checking
|
||||
|
||||
m_szEventCategory = "VolumeSet Event";
|
||||
m_szEventName = htmVolEvent[ eventId ];
|
||||
return ( ( eventId == VS_EVT_REBUILDING ) || ( eventId == VS_EVT_DEGRADED ) ? true : false );
|
||||
|
||||
case EVENT_RAIDSET:
|
||||
/// The meaning of eventId
|
||||
/// 0(RS_EVT_CREATE) - Create RaidSet
|
||||
/// 1(RS_EVT_DELETE) - Delete RaidSet
|
||||
/// 2(RS_EVT_EXPAND) - Expand RaidSet
|
||||
/// 3(RS_EVT_REBUILD) - Rebuild RaidSet
|
||||
/// 4(RS_EVT_DEGRADED) - RaidSet Degraded
|
||||
|
||||
m_szEventCategory = "RaidSet Event";
|
||||
m_szEventName = htmRaidEvent[ eventId ];
|
||||
return ( ( eventId == RS_EVT_REBUILD ) || ( eventId == RS_EVT_DEGRADED ) ? true : false );
|
||||
|
||||
/// for test code
|
||||
///case EVENT_NEW_83782D:
|
||||
/// m_szEventCategory = "New Events";
|
||||
/// m_szEventName = htmNewEventStr[ eventId ];
|
||||
/// return ( eventId == GHM_GUI_LOGIN ? true : false );
|
||||
|
||||
default:
|
||||
m_szEventCategory = "";
|
||||
m_szEventName = "";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
AutoDisableUpload.h
|
||||
-----------------------------------------
|
||||
begin : 2011/07/26
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#ifndef __AUTODISABLEUPLOAD_H__
|
||||
#define __AUTODISABLEUPLOAD_H__
|
||||
|
||||
#include "arclib.h"
|
||||
#include "Logger.h"
|
||||
#include <string>
|
||||
|
||||
class CAutoDisableUpload
|
||||
{
|
||||
// Attributes
|
||||
private:
|
||||
std::string m_szEventCategory;
|
||||
std::string m_szEventName;
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Operations
|
||||
private:
|
||||
/// @brief 업로드 방지 이벤트 발생 여부 확인.
|
||||
/// @param eventCategory [in] 이벤트 카테고리
|
||||
/// @param eventId [in] 이벤트 카테고리별 이벤트 아이디
|
||||
/// @return 업로드 방지 이벤트면 true, 그렇지 않으면 false.
|
||||
bool IsDisableUpload( int eventCategory, int eventId );
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
CAutoDisableUpload();
|
||||
virtual ~CAutoDisableUpload();
|
||||
|
||||
/// @brief 업로드 방지 이벤트가 발생했으면 /user/service/vmasd.disable 파일을 생성해서
|
||||
/// 업로드가 방지 되도록 한다.
|
||||
/// @param eventCategory [in] 이벤트 카테고리
|
||||
/// @param eventId [in] 이벤트 카테고리별 이벤트 아이디
|
||||
/// @return 없음.
|
||||
void DoProcess( int eventCategory, int eventId );
|
||||
};
|
||||
|
||||
#endif // __AUTODISABLEUPLOAD_H__
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "Child.h"
|
||||
#include "SmsSender.h"
|
||||
#include "ArecaWrapper.h"
|
||||
#include "UdpListener.h"
|
||||
#include "EventDataManager.h"
|
||||
#include "AutoDisableUpload.h"
|
||||
|
||||
|
||||
#define MAXSIZEOFSTR 128
|
||||
|
||||
/// @brief child Process 종료 Signal 을 전달받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigTermChild( int nSignalNumber )
|
||||
{
|
||||
// Signal Number 에 따른 로깅처리.
|
||||
if( nSignalNumber == SIGTERM )
|
||||
{
|
||||
_LOG( LWAR, "Child Process[%d] exit job start by user signal [SIGTERM]", getpid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
_LOG(LWAR, "Child Process[%d] exit job start by abnormal signal [%d]", getpid(), nSignalNumber );
|
||||
}
|
||||
_LOG(LWAR, "Child Process[%d] exit job end. Good Bye..", getpid());
|
||||
|
||||
usleep(500000);
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
/// @brief child Process 에서 Core 생성 관련 Signal 을 받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigCoreChild( int nSignalNumber )
|
||||
{
|
||||
_LOG(LERR, "Child Process[%d] abnoraml exit. Check Core file. Receive signal [%d]", getpid(), nSignalNumber );
|
||||
//ERROR_LOG( "Core file path : [%s/%s.core]", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
// Process 종료관련 작업 추가
|
||||
|
||||
// Log Directory 상에 Core 파일 생성처리.
|
||||
chdir( g_envConfig.szLogDir.c_str() );
|
||||
signal( nSignalNumber, SIG_DFL );
|
||||
// Core dump 생성을 위한 신호 발생처리.=> ?
|
||||
raise( nSignalNumber );
|
||||
}
|
||||
|
||||
|
||||
/// @brief child process signal 처리 설정을 위한 함수
|
||||
/// @return void
|
||||
static void SetSignalChild( void )
|
||||
{
|
||||
sigset_t set;
|
||||
struct sigaction act;
|
||||
sigfillset( &set );
|
||||
sigprocmask( SIG_SETMASK, &set, NULL );
|
||||
memset( &act, 0x00, sizeof(act) );
|
||||
sigfillset( &act.sa_mask );
|
||||
/* 무시할 신호 목록 */
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction( SIGPIPE, &act, NULL); /* 파이프 디스크립터 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정 */
|
||||
sigaction( SIGHUP , &act, NULL); /* Process를 기동시킨 관리자의 로그아웃시 발생 시그널 */
|
||||
sigaction( SIGINT , &act, NULL); /* ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음 */
|
||||
sigaction( SIGQUIT, &act, NULL); /* 키보드에 의한 Abort 신호 처리 => ? */
|
||||
// Child 프로세스는 자식 프로세스가 존재하지 않으므로 그냥 무시처리함.
|
||||
sigaction( SIGCHLD, &act, NULL);
|
||||
/* 각종 에러나 사용자의 종료 신호 처리 */
|
||||
act.sa_handler = SigTermChild;
|
||||
sigaction( SIGTERM, &act, NULL); /* kill -TERM 에 의한 프로세스 종료시 */
|
||||
/* Core 관련 signal 처리 : 오류 처리 및 Debug(core dump) 목적 */
|
||||
// dadamin : 팀 기준 적용
|
||||
//act.sa_handler = SigCoreChild;
|
||||
//sigaction( SIGILL , &act, NULL); /* Illegal instruction */
|
||||
//sigaction( SIGFPE , &act, NULL); /* Erroneout arithmetic operation */
|
||||
//sigaction( SIGBUS , &act, NULL); /* Access to undefined portion of a memory object */
|
||||
//sigaction( SIGSEGV, &act, NULL); /* Invalid memory reference */
|
||||
//sigaction( SIGSYS , &act, NULL); /* Bad System Call */
|
||||
//sigaction( SIGXCPU, &act, NULL); /* CPU-time limit exceeded */
|
||||
//sigaction( SIGXFSZ, &act, NULL); /* File-size limit exceeded */
|
||||
|
||||
|
||||
sigemptyset(&set); /* 신호 처리기 처리 설정 위한 블록 해제 */
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
}
|
||||
|
||||
/// @brief Child Process 의 main 함수
|
||||
int ChildMain(void)
|
||||
{
|
||||
bool bRet = false;
|
||||
int nFailCnt = 0;
|
||||
// set child signal
|
||||
SetSignalChild();
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
setproctitle( "Child [initialize process]");
|
||||
#endif
|
||||
|
||||
|
||||
char szTime[MAXSIZEOFSTR];
|
||||
time_t ltime;
|
||||
struct tm *pTm = NULL;
|
||||
char szHostname[MAXSIZEOFSTR];
|
||||
|
||||
// ** SMS Sender 객체 생성 및 초기화
|
||||
CSmsSender objSmsSender(g_envConfig.szSMSHost, g_envConfig.nSMSPort, g_envConfig.szSMSSendfile);
|
||||
bRet = objSmsSender.Init();
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing SmsSender Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** SMS Sender 객체 생성 및 초기화
|
||||
// 2015-06-26 두 번째 파라메터는 더이상 의미가 없다.
|
||||
CArecaWrapper objAreca(g_envConfig.nEventLevel);
|
||||
if( objAreca.InitArecaControllers() < 0 )
|
||||
{
|
||||
LOG(LERR, "Initializing Areca RAID Controller has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** EventDataManager 객체 생성 및 초기화
|
||||
CEventDataManager objDataManager;
|
||||
bRet = objDataManager.Init();
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing SmsSender Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** Raid Event Monitor 객체 생성 및 초기화
|
||||
|
||||
// ** UDP Listener 객체 생성 및 초기화
|
||||
CUdpListener udpObj(&objDataManager);
|
||||
// report thread port :
|
||||
bRet = udpObj.Init(g_envConfig.nReportPort);
|
||||
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing UdpListener Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
udpObj.Start();
|
||||
|
||||
// 현재 hostname
|
||||
// hostname이 변경되면 반영되지 않는다. 반영이 꼭필요하다면 while구문 안으로 넣으면 된다.
|
||||
if( ::gethostname(szHostname, MAXSIZEOFSTR) < 0 )
|
||||
{
|
||||
_LOG(LWAR, "gethostname failed. : %s", szHostname);
|
||||
::snprintf(szHostname, MAXSIZEOFSTR, "%s", "error.hostname.com");
|
||||
}
|
||||
nFailCnt = 0;
|
||||
while( 1 )
|
||||
{
|
||||
list<CEventData> listRet;
|
||||
|
||||
if( objAreca.GetEvent(GET_EVENT_ALL, listRet) == false )
|
||||
{
|
||||
if( nFailCnt < 3 )
|
||||
{
|
||||
nFailCnt++;
|
||||
_LOG(LWAR, "Get RAID Event Data Failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LERR, "Get RAID Event Data Failed. %d(th). Send SMS.",nFailCnt);
|
||||
nFailCnt = 0;
|
||||
|
||||
// 현재 시각 설정
|
||||
time((time_t *)<ime);
|
||||
pTm = ::localtime((time_t *)<ime);
|
||||
::memset(szTime, 0, sizeof(szTime));
|
||||
::snprintf(szTime, MAXSIZEOFSTR, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
|
||||
pTm->tm_year+1900, pTm->tm_mon +1, pTm->tm_mday,
|
||||
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
|
||||
|
||||
objSmsSender.SendToWebServ(szHostname, szTime ,"Can NOT Receive Data From RAID Controller!");
|
||||
}
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
nFailCnt = 0; // 성공하면 실패 카운트를 리셋한다.
|
||||
|
||||
// 받아온 Raid Event 저장
|
||||
bRet = objDataManager.SetCurrentData(listRet);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "SetCurrentData Failed. but it's Impossible. Check ArecaWrapper::GetEvent().");
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
// SMS 전송 목록
|
||||
listRet.clear();
|
||||
bRet = objDataManager.GetSmsEvent(listRet);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "GetSmsEvent() failed.");
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for (list<CEventData>::iterator it=listRet.begin(); it!=listRet.end(); it++)
|
||||
{
|
||||
// NEW 2019-09-16 huibong 불필요 "Battery Module Failed" event 는 전송하지 않는다. (#32795)
|
||||
// - "Battery Module Failed" event 는 운영자가 수신해도 할 작업이 없음
|
||||
// - 하지만 일 10~20 건 정도가 발생하여 운영자에게 불필요 event 가 전달됨
|
||||
// - 이와 관련 KT 운영팀 윤철희 실장이 해당 event 는 무시하도록 처리해 달라고 해서...
|
||||
// - 해당 메시지 발생시 운영자에게 event 전송하지 않도록 한다.
|
||||
// - 실제로 CEventDataManager 모듈에서도 처리가능하지만...
|
||||
// - 본 모듈에서 실제 event 전송을 담당하므로.. 본 모듈에서 무시 처리하도록 수정함.
|
||||
// BUG 2020-01-10 huibong 불필요 "Battery Module Failed" event 미전송 관련 버그 수정 (#32911)
|
||||
// - 실제로 Module 단어와 Failed 단어 사이에 공백이 3개 존재
|
||||
// - 이로 인해 해당 event 가 계속 전송되는 상황 발견됨
|
||||
// - 이에 Battery Module" check 후 Failed 문자열 check 하도록 수정
|
||||
std::string::size_type find_result;
|
||||
find_result = it->m_szEventData.find( "Battery Module" );
|
||||
if( find_result != std::string::npos )
|
||||
{
|
||||
find_result = it->m_szEventData.find( "Fail" );
|
||||
if( find_result != std::string::npos )
|
||||
{
|
||||
_LOG( LDBG, "Do not send event with operator requests [%s]", it->m_szEventData.c_str() );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pTm = ::localtime(&(it->m_evtTime));
|
||||
::memset(szTime, 0, sizeof(szTime));
|
||||
::snprintf(szTime, MAXSIZEOFSTR, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
|
||||
pTm->tm_year+1900, pTm->tm_mon +1, pTm->tm_mday,
|
||||
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
|
||||
_LOG(LWAR, "SMS Sent.[%s::%s:%s]",szHostname, szTime, it->m_szEventData.c_str());
|
||||
//FIXME:호출하면 SMS가 발송된다... :많은사람에게 문자가 수신되므로 디버깅 때는 가급적 자제할것. please........
|
||||
objSmsSender.SendToWebServ(szHostname, szTime ,it->m_szEventData.c_str());
|
||||
|
||||
/// 2011.07.26, 수정자 : 장희준
|
||||
/// 업로드 자동 방지
|
||||
CAutoDisableUpload autoDisableUpload;
|
||||
autoDisableUpload.DoProcess( it->GetEventCategory(), it->GetEventId() );
|
||||
}
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
}
|
||||
|
||||
|
||||
// wait
|
||||
while(1)
|
||||
{
|
||||
// 그냥 시그널 대기
|
||||
pause();
|
||||
}
|
||||
|
||||
//잠시 대기 후 종료처리.
|
||||
usleep(500000);
|
||||
// exit( EXIT_SUCCESS );
|
||||
return EXIT_SUCCESS; // fork 를 수행한 함수에서 exit 함수 호출을 통한 종료처리
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/***************************************************************************
|
||||
fhs_raidmond Header ( Child.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/09
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __CHILD_PROCESS_H__
|
||||
#define __CHILD_PROCESS_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief Child Process ÀÇ main ÇÔ¼ö
|
||||
/// @return
|
||||
int ChildMain( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CHILD_PROCESS_H__ */
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#define MaxRTTime 5
|
||||
#define MaxRecvBuffSize (20 * 1024)
|
||||
|
||||
void handleAlarm(int signal)
|
||||
{
|
||||
return; // just return and interupt.
|
||||
}
|
||||
|
||||
|
||||
// main function
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
if(argc != 4)
|
||||
{
|
||||
cerr << PROG_NAME << " Version :" << PROG_VERSION << endl;
|
||||
cerr << "Usage: " << PROG_NAME << " server-ip port mode" << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static bool success = false;
|
||||
// parse command line arguments
|
||||
string host = argv[1];
|
||||
int port = atoi(argv[2]);
|
||||
string mode = argv[3];
|
||||
|
||||
//cout << "arguments : " << host << "," << port << "," << mode << endl;
|
||||
|
||||
int r = -1;
|
||||
struct sockaddr_in cliaddr;
|
||||
int addr_len = sizeof(cliaddr);
|
||||
char recvbuf[MaxRecvBuffSize];
|
||||
string result;
|
||||
|
||||
// socket initialize
|
||||
int s = -1;
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
cerr << "Socket Create: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = MaxRTTime;
|
||||
timeout.tv_usec = 0;
|
||||
int optlen = sizeof(timeout);
|
||||
|
||||
int errtimeout = -1;
|
||||
if( setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, (socklen_t)optlen) < 0)
|
||||
{
|
||||
struct sigaction sigact, oldact;
|
||||
sigact.sa_handler = handleAlarm;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
#ifdef SA_INTERRUPT
|
||||
sigact.sa_flags |= SA_INTERRUPT;
|
||||
#endif // SA_INTERRUPT
|
||||
if(sigaction(SIGALRM, &sigact, &oldact) < 0)
|
||||
{
|
||||
cerr << "sigaction error: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
errtimeout = EINTR;
|
||||
}
|
||||
else
|
||||
errtimeout = EAGAIN;
|
||||
|
||||
struct sockaddr_in SocAddr;
|
||||
|
||||
SocAddr.sin_family = AF_INET;
|
||||
SocAddr.sin_port = htons(port);
|
||||
//SocAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (inet_aton(host.c_str(), &SocAddr.sin_addr)==0)
|
||||
{
|
||||
cerr << "inet_aton() failed: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// send
|
||||
int len = mode.length();
|
||||
if( sendto( s, mode.c_str(), mode.length(), 0, (struct sockaddr *)&SocAddr, sizeof(SocAddr) ) != len)
|
||||
{
|
||||
cerr << "sendto error : errno :"<< errno << " errmg:" << strerror(errno) << endl;
|
||||
goto GOTO_END;
|
||||
}
|
||||
|
||||
if( errtimeout == EINTR )
|
||||
{
|
||||
alarm(MaxRTTime);
|
||||
}
|
||||
|
||||
// receive
|
||||
do
|
||||
{
|
||||
memset(recvbuf, 0, MaxRecvBuffSize);
|
||||
r = recvfrom( s, (char *)&recvbuf, (unsigned int)MaxRecvBuffSize, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&addr_len );
|
||||
//cerr << "nREAD = " << r << "," << errno << endl;
|
||||
|
||||
if(r >= 0)
|
||||
result += recvbuf;
|
||||
else
|
||||
{
|
||||
if( errno == errtimeout ) // timeout
|
||||
{
|
||||
cerr << "3:" << (long)time(NULL) << ":Disabled" << endl;
|
||||
goto GOTO_END;
|
||||
}
|
||||
}
|
||||
|
||||
} while (r <= 0);
|
||||
|
||||
cout << result << endl;
|
||||
|
||||
if (result.size())
|
||||
success = true;
|
||||
|
||||
GOTO_END:
|
||||
close(s);
|
||||
|
||||
return success ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
Areca Library Event Data Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/21
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EVENT_DATA__
|
||||
#define __EVENT_DATA__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
/// @brief CEventData
|
||||
/// EventData 는 Areca library로부터 받아오는 raid event 정보를 저장한다.
|
||||
/// 내부적으로 Thread를 사용하고있다.
|
||||
class CEventData
|
||||
{
|
||||
private:
|
||||
int m_nEventCategory;
|
||||
int m_nEventId;
|
||||
|
||||
public:
|
||||
/// @brief Areca Library에서 얻어온 데이터의 시간값을 저장한다.
|
||||
time_t m_evtTime;
|
||||
std::string m_szEventData;
|
||||
|
||||
public:
|
||||
/// @brief 생성자
|
||||
CEventData(){};
|
||||
|
||||
/// @brief 소멸자
|
||||
~CEventData(){};
|
||||
|
||||
inline void SetEventType( int eventCategory, int evnetId )
|
||||
{
|
||||
m_nEventCategory = eventCategory;
|
||||
m_nEventId = evnetId;
|
||||
}
|
||||
|
||||
inline int GetEventCategory() { return m_nEventCategory; };
|
||||
inline int GetEventId() { return m_nEventId; };
|
||||
|
||||
/// @brief Areca Library에서 얻어온 이벤트 데이터를 저장한다.
|
||||
///< 데이터의 형태로 반복여부를 확인하여 중복 반복시 최초 1개의 데이터만을 알림하도록 설계되었다.
|
||||
|
||||
inline bool operator==(const CEventData& t)
|
||||
{
|
||||
return ( (t.m_evtTime == m_evtTime) && (t.m_szEventData == m_szEventData) );
|
||||
}
|
||||
};
|
||||
#endif // __EVENT_DATA__
|
||||
@@ -0,0 +1,163 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "EventDataManager.h"
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define REPEAT_ALLOW_TIME 60*60
|
||||
|
||||
|
||||
// 생성자
|
||||
CEventDataManager::CEventDataManager()
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
}
|
||||
|
||||
// 소멸자
|
||||
CEventDataManager::~CEventDataManager()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
bool CEventDataManager::Init(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CEventDataManager::GetAllData(list<CEventData>& listRet)
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
|
||||
if ( m_Current.size() < 1 || m_Old.size() < 1 )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "Data have Nothing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
listRet = m_Current;
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
|
||||
int CEventDataManager::GetLatestData( CEventData& resData )
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
|
||||
if ( m_Current.size() < 1 || m_Old.size() < 1 )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "Data have Nothing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if( m_Old.back().m_evtTime == m_Current.back().m_evtTime )
|
||||
{ // ( 과거와 현재 최종 이벤트 시각이 동일하면 변화가 없는 것이다. )
|
||||
resData = m_Current.back();
|
||||
resData.m_szEventData = "NO EVENT";
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 과거와 현재 최종 이벤트 시각이 다르면 이벤트가 추가된 것이다.
|
||||
resData = m_Current.back();
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CEventDataManager::SetCurrentData(list<CEventData>& listRet)
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
if( listRet.empty() )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "EventData is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 들어온 데이터는 모두 시간순으로 정렬한다. (오름차순)
|
||||
// Old 데이터를 지운다.
|
||||
m_Old.clear();
|
||||
//현재 값이 비어있을 경우 (최초 실행으로 간주함)
|
||||
if( m_Current.empty() == true)
|
||||
{
|
||||
m_Old = listRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Old = m_Current;
|
||||
}
|
||||
m_Current = listRet;
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEventDataManager::GetSmsEvent(list<CEventData>& listRet)
|
||||
{
|
||||
CEventData fetchedData;
|
||||
CEventData lastDataOfOld;
|
||||
list<CEventData> eventData = m_Current;
|
||||
list<CEventData> listFindTemp;
|
||||
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
|
||||
if( m_Current.size() == 0 )
|
||||
{
|
||||
LOG(LERR, "List have No Data");
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return false;
|
||||
}
|
||||
// 과거의 최신 데이터를 저장한다.
|
||||
m_SentOld = m_Old.back();
|
||||
// 현재 리스트의 뒤쪽(최신)부터 동일 데이터를 찾는다.
|
||||
// (데이터에 시간 값이 포함되어 있기 때문에 완전히 동일한 데이터는 없는 것으로 간주한다.)
|
||||
// (있을 경우 무시해도 되지 않을까?)
|
||||
|
||||
listFindTemp.push_back(m_SentOld);
|
||||
// find_end를 사용하기 위해서 원소가 1개인 리스트를 생성한다.
|
||||
list<CEventData>::iterator it = find_end(m_Current.begin(), m_Current.end(), listFindTemp.begin(), listFindTemp.end());
|
||||
// 뒤쪽부터 원소가 1개인 리스트(listFindTemp)를 찾는다.
|
||||
// find_end()는 집합에 속하는 부분집합을 찾는다.
|
||||
|
||||
|
||||
// 찾아낸 데이터의 뒤쪽 부분은 신규 데이터이다.
|
||||
if( it == m_Current.end() )
|
||||
{ // end()와 같다면, 끝까지 찾지 못한 것을 의미한다. (NOT FOUND)
|
||||
// 찾지 못한 것은 전체가 다 새로운 것이다.
|
||||
_LOG(LINF, "List has NEW Event perfectly.");
|
||||
it = m_Current.begin();
|
||||
}
|
||||
else
|
||||
{ // 찾아낸 데이터의 다음 데이터를 가리키도록 한다.
|
||||
++it;
|
||||
}
|
||||
|
||||
// 신규 데이터 목록 중 앞쪽(오래된)부터 중복된 데이터인지를 검사한다.
|
||||
for( ; it != m_Current.end(); it++)
|
||||
{
|
||||
if( it->m_szEventData == m_SentOld.m_szEventData
|
||||
&& it->m_evtTime - m_SentOld.m_evtTime < REPEAT_ALLOW_TIME
|
||||
&& it->m_evtTime - m_SentOld.m_evtTime >= 0 )
|
||||
{ // 내용이 중복되고 마지막 이벤트로부터 1시간 미만 차이나면?
|
||||
// BUG: Areca bug로 시간이 역순할 수 있다. REPEAT_ALLOW_TIME보다 작은 음수 값이 나오게 되면 무시하면 안된다.
|
||||
_LOG(LINF, "There is Repeted Event.[%s]",it->m_szEventData.c_str());
|
||||
// 중복 되면 버린다.(과거 데이터를 우선한다)
|
||||
continue;
|
||||
}
|
||||
|
||||
// 중복 데이터가 아니면 결과에 추가 한다.(SMS발송 대상)
|
||||
listRet.push_back(*it);
|
||||
m_SentOld = *it;
|
||||
_LOG(LDBG, "ADD : [%lu::%s]", it->m_evtTime, it->m_szEventData.c_str());
|
||||
}
|
||||
// SMS발송 대상이 없을 경우 디버깅 로그만 남긴다.
|
||||
if( listRet.size() == 0 )
|
||||
{
|
||||
LOG(LDBG, "There is No New Event.");
|
||||
}
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/***************************************************************************
|
||||
SMS Raid Event Data Manager Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/24
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EVENT_DATA_MANAGER__
|
||||
#define __EVENT_DATA_MANAGER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include "Logger.h"
|
||||
#include "EventData.h"
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief CEventDataManager
|
||||
/// EventDataManager 는 Areca library로부터 받아오는 raid event 정보를 저장한다.
|
||||
class CEventDataManager
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
CEventDataManager();
|
||||
|
||||
/// @brief 소멸자
|
||||
~CEventDataManager();
|
||||
|
||||
//TODO:
|
||||
bool Init();
|
||||
bool SetCurrentData(list<CEventData>& listRet);
|
||||
bool GetSmsEvent(list<CEventData>& listRet);
|
||||
int GetLatestData( CEventData& resData );
|
||||
bool GetAllData(list<CEventData>& listRet);
|
||||
private:
|
||||
// TODO:
|
||||
list<CEventData> m_Current;
|
||||
list<CEventData> m_Old;
|
||||
CEventData m_SentOld;
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
};
|
||||
#endif // __EVENT_DATA_MANAGER__
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "Config.h"
|
||||
#include "GetConfig.h"
|
||||
|
||||
/// @brief config value chech
|
||||
/// @param szValue [in] value
|
||||
/// @param conf [in] Config 객체
|
||||
/// @param defsection [in] default section
|
||||
/// @param defkey [in] default key
|
||||
/// @return 성공시 true, 오류 발생시 false 를 반환.
|
||||
static bool CheckValue(std::string& szValue, Config& conf, const std::string& defsection, const std::string& defkey)
|
||||
{
|
||||
if( szValue.size() > 0 )
|
||||
return true;
|
||||
|
||||
if( defsection.size() <= 0 || defkey.size() <= 0 )
|
||||
return false;
|
||||
|
||||
conf.GetConfig( defsection, defkey, szValue );
|
||||
|
||||
if( szValue.size() > 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GetConfig( const std::string& szConfFile, struct st_config& stConfig, std::string& errorMessage )
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
// Config 처리를 위한 객체 생성
|
||||
Config conf;
|
||||
|
||||
// Config File open
|
||||
if( conf.Open( szConfFile) == false )
|
||||
{
|
||||
errorMessage = "Config file open failed.[" + szConfFile + "]";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string szValue;
|
||||
szValue.clear();
|
||||
|
||||
// log path
|
||||
if( conf.GetConfig( PROG_NAME, "DEFAULT_LOG_DIR", szValue ) == false )
|
||||
{
|
||||
if( !CheckValue(szValue, conf, "COMMON", "DEFAULT_LOG_DIR") )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->LOG_DIR";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stConfig.szLogDir = szValue;
|
||||
|
||||
szValue.clear();
|
||||
// log level
|
||||
if( conf.GetConfig( PROG_NAME, "LOG_LEVEL", szValue ) == false )
|
||||
{
|
||||
if( !CheckValue(szValue, conf, "COMMON", "LOG_LEVEL") )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->LOG_LEVEL";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stConfig.nLogLevel = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
// check term
|
||||
if( conf.GetConfig( PROG_NAME, "HEALTH_CHECK_TERM", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->HEALTH_CHECK_TERM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->HEALTH_CHECK_TERM";
|
||||
return false;
|
||||
}
|
||||
stConfig.nCheckTerm = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
// report port
|
||||
if( conf.GetConfig( PROG_NAME, "REPORT_THREAD_PORT", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->REPORT_THREAD_PORT";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->REPORT_THREAD_PORT";
|
||||
return false;
|
||||
}
|
||||
stConfig.nReportPort = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
//event level
|
||||
if( conf.GetConfig( PROG_NAME, "EVENT_LEVEL", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->EVENT_LEVEL";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->EVENT_LEVEL";
|
||||
return false;
|
||||
}
|
||||
stConfig.nEventLevel = atoi(szValue.c_str());
|
||||
szValue.clear();
|
||||
//sms send host
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_HOST", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
stConfig.szSMSHost = szValue;
|
||||
|
||||
szValue.clear();
|
||||
//sms send port
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_PORT", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_PORT";
|
||||
return false;
|
||||
}
|
||||
stConfig.nSMSPort = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
//sms send file
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_URI", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_FILE";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_FILE";
|
||||
return false;
|
||||
}
|
||||
stConfig.szSMSSendfile = szValue;
|
||||
szValue.clear();
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/***************************************************************************
|
||||
rc_rmcd ( File Replication & Cache Control Daemon ) Header ( GetConfig.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/03
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __GET_CONFIG_H__
|
||||
#define __GET_CONFIG_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief config file parsing and save to stConfig function
|
||||
/// @param szConfFile [in] Conf 파일에 대한 경로 및 파일 정보
|
||||
/// @param stConfig [out] Conf 파일의 정보를 저장하기 위한 st_config 참조변수
|
||||
/// @param errorMessage [out] 오류발생시 해당 오류 정보를 저장하여 반환하기 위한 참조변수
|
||||
/// @return 성공시 true, 오류 발생시 false 를 반환. 상세한 오류 정보는 errorMessage 변수에 저장됨.
|
||||
bool GetConfig( const std::string& szConfFile, struct st_config& stConfig, std::string& errorMessage);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __GET_CONFIG_H__ */
|
||||
@@ -0,0 +1,87 @@
|
||||
#****************************************************************************
|
||||
# Makefile for Arcmond
|
||||
# -----------------------------------------
|
||||
#
|
||||
# begin : 2010/05/17
|
||||
# copyright : (C) 2005 SolutionBox Inc.
|
||||
# author : Service 1 Team
|
||||
# email : svc1@solbox.com
|
||||
# version : 3.0.0
|
||||
#
|
||||
# CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or with out
|
||||
# modification, are not permitted in outside of SolutionBox Inc.
|
||||
#*****************************************************************************
|
||||
|
||||
# Program info
|
||||
PROG_NAME = arcmond
|
||||
PROG_NAME_C = arcmond_client
|
||||
#REVISION = `svnversion -n .`
|
||||
REVISION = 1507
|
||||
BUILD_DATE = `date +%Y%m%d%H%M%S`
|
||||
PROG_VERSION = 3.5.0.$(REVISION)-$(BUILD_DATE)
|
||||
DEFAULT_CONFIG_FILE = /user/service/etc/util.conf
|
||||
INSTALL_BIN = /user/service/bin
|
||||
OSBITS := $(shell getconf LONG_BIT)
|
||||
|
||||
# Compiler info
|
||||
CC = /usr/bin/g++
|
||||
|
||||
CFLAGS = -Wall -O3 -g -Wreturn-type -Wunused -Wuninitialized \
|
||||
-Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual\
|
||||
-fno-rtti -D_REENTRANT -Wno-unused -Wno-non-virtual-dtor
|
||||
|
||||
LFLAGS = -lpthread
|
||||
|
||||
# DEBUG or RELEASE Mode select
|
||||
#DFLAGS = -D_DEBUG_ -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\" -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
|
||||
DFLAGS = -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\" -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
|
||||
|
||||
|
||||
# Application Enviroment
|
||||
APP = $(PROG_NAME)
|
||||
|
||||
DIR_INCLUDE = -I./. -I../lib -I ../external/include #-I /user/db/pgsql/include -I../
|
||||
DIR_LIB = -L../lib -L../external/bin/
|
||||
|
||||
OBJ = GetConfig.o Child.o main.o ArecaWrapper.o UdpListener.o SmsSender.o EventDataManager.o AutoDisableUpload.o
|
||||
|
||||
LIBS = ../lib/libInterCommon.a ../external/bin/libarclib${OSBITS}.a
|
||||
|
||||
ifeq ($(CLIENT), yes)
|
||||
PROG_NAME = $(PROG_NAME_C)
|
||||
OBJ = Client.o
|
||||
LIBS =
|
||||
endif
|
||||
|
||||
############################
|
||||
|
||||
all:$(APP)
|
||||
#rm -f main.o
|
||||
sync
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
test: $(OBJ)
|
||||
$(CC) $(LFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
$(PROG_NAME): $(OBJ)
|
||||
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
|
||||
|
||||
tael: $(OBJ) SmsSender.o
|
||||
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
|
||||
client:
|
||||
$(MAKE) CLIENT="yes"
|
||||
|
||||
clean:
|
||||
-rm -f *.o core *.out *.log
|
||||
-rm -f $(APP)
|
||||
sync
|
||||
|
||||
|
||||
install : $(APP)
|
||||
-cp $(APP) $(INSTALL_BIN)/$(APP)
|
||||
sync
|
||||
|
||||
# End of Makefile
|
||||
@@ -0,0 +1,256 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "SmsSender.h"
|
||||
#include <iterator>
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 9216
|
||||
#define MaxSizeOfTRxBuffer 1024
|
||||
|
||||
|
||||
string CSmsSender::RemoveBlankSpace(const char* pszData, size_t nLength)
|
||||
{
|
||||
char * szTemp = NULL;
|
||||
string strReturn;
|
||||
const char * src;
|
||||
char * dest;
|
||||
|
||||
|
||||
szTemp = (char*) ::malloc(sizeof(char) * nLength +1);
|
||||
::memset(szTemp, 0 , sizeof(char)*nLength +1);
|
||||
|
||||
src = pszData;
|
||||
dest = szTemp;
|
||||
|
||||
if( pszData == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
if( *src == '\0' )
|
||||
{
|
||||
strReturn = src;
|
||||
return strReturn;
|
||||
}
|
||||
// start with 2nd position
|
||||
src++;
|
||||
while ( src <= (pszData + nLength) && *(src-1) != '\0' )
|
||||
{
|
||||
if( *(src-1) == ' ' && *(src) == ' ' )
|
||||
{ // 연속된 공백이 발견되면, 스킵한다.
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
*dest = *(src-1);
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
// 종료표기
|
||||
dest++;
|
||||
*(dest) = '\0';
|
||||
|
||||
strReturn = szTemp;
|
||||
if (szTemp != NULL)
|
||||
{
|
||||
free(szTemp);
|
||||
szTemp = NULL;
|
||||
}
|
||||
return strReturn;
|
||||
}
|
||||
char hexchars[] = "0123456789ABCDEF";
|
||||
string CSmsSender::PostDataEncode(const char *pszCommand, size_t length)
|
||||
{
|
||||
int i;
|
||||
char tmpBuffer[MaxSizeOfTRxBuffer];
|
||||
string strReturn;
|
||||
|
||||
if( pszCommand == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
::memset(tmpBuffer, 0 , MaxSizeOfTRxBuffer);
|
||||
i = 0;
|
||||
while( *pszCommand != '\0' )
|
||||
{
|
||||
if( *pszCommand == ' ' )
|
||||
{ // ' ' => '+'
|
||||
tmpBuffer[i++] = '+';
|
||||
pszCommand++;
|
||||
}
|
||||
else if(*pszCommand == '%')
|
||||
{ // % => %%
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = '%';
|
||||
pszCommand++;
|
||||
}
|
||||
else if( (*pszCommand < '0' && *pszCommand != '-' && *pszCommand != '.' )
|
||||
|| (*pszCommand < 'A' && *pszCommand > '9' )
|
||||
|| (*pszCommand > 'Z' && *pszCommand < 'a' && *pszCommand != '_' )
|
||||
|| (*pszCommand > 'z' ) )
|
||||
{
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand >> 4];
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand & 15];
|
||||
pszCommand++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpBuffer[i++] = *pszCommand++;
|
||||
}
|
||||
}
|
||||
tmpBuffer[i] = '\0';
|
||||
|
||||
strReturn = tmpBuffer;
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CSmsSender::CSmsSender(const std::string& szHost, const int nPort, const std::string& szPath)
|
||||
: CBaseSocket( SOCKET_NOT_VALID), m_szHost(szHost), m_nPort(nPort), m_szPath(szPath)
|
||||
{
|
||||
// 생성자
|
||||
}
|
||||
|
||||
CSmsSender::~CSmsSender()
|
||||
{
|
||||
// 소멸자에 BaseSocket의 명시적 Close 처리를 한다.
|
||||
Close();
|
||||
}
|
||||
|
||||
bool CSmsSender::Init(void)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
// 데이터 체크
|
||||
if( m_szHost.empty() || m_nPort < 0 || m_szPath.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSmsSender::SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg)
|
||||
{
|
||||
string szHost;
|
||||
string szTime;
|
||||
string szMsg;
|
||||
char szSndBuffer[DEFAULT_BUFFER_SIZE];
|
||||
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
|
||||
bool bRet = false;
|
||||
int nRet = 0;
|
||||
|
||||
|
||||
if( pszHost.empty() || pszMsg.empty() || pszTime.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect
|
||||
bRet = Connect(m_szHost, m_nPort);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Socket Connect Error.[%s:%d]", m_szHost.c_str(), m_nPort);
|
||||
return false;
|
||||
}
|
||||
if( IsValidSocket() == false )
|
||||
{
|
||||
LOG(LERR, "Invalid Socket.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
::bzero(szSndBuffer, DEFAULT_BUFFER_SIZE);
|
||||
::bzero(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
|
||||
szHost = PostDataEncode(pszHost.c_str(), pszHost.size());
|
||||
szTime = PostDataEncode(pszTime.c_str(), pszTime.size());
|
||||
szMsg = RemoveBlankSpace(pszMsg.c_str(), pszMsg.size());
|
||||
LOG(LDBG, "SMSMsg = [%s]", szMsg.c_str());
|
||||
szMsg = PostDataEncode(szMsg.c_str(), szMsg.size());
|
||||
|
||||
|
||||
// CHG 2019-09-16 huibong HTTP 관련 줄바꿈문자 LF->CR+LF 변경 (#32794)
|
||||
// - CVE-2016-8743 이슈에 따라 Apache 2.2.32 버전부터 HTTP header 상에서
|
||||
// - 줄바꿈문자가 CR+LF 가 아닌 경우 HTTP 400 응답 발생
|
||||
// - 이를 해결하기 위해 기존 줄바꿈 문자 \n -> \r\n 으로 변경처리한다.
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "GET %s?host=%s&time=%s&msg=%s HTTP/1.0\r\n"\
|
||||
"Content-Type: text/plain\r\n"\
|
||||
"User-Agent: Arcmond\r\n"\
|
||||
"Host: %s\r\n"\
|
||||
"Connection: close\r\n"\
|
||||
"Cache-Control: no-cache\r\n\r\n"
|
||||
,m_szPath.c_str(), szHost.c_str(), szTime.c_str(), szMsg.c_str() ,m_szHost.c_str());
|
||||
|
||||
//DEBUG_LOG("%s", szSndBuffer);
|
||||
//요청 전송 시작
|
||||
nRet = WriteN(&szSndBuffer, ::strlen(szSndBuffer)+1);
|
||||
// MAX_SEND_RETRY_COUNT 회수만큼 재시도 후 실패처리된다.
|
||||
if( nRet == 0 )
|
||||
{
|
||||
LOG(LERR, "write socket closed.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{
|
||||
LOG(LERR, "write socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 응답 결과 받기.
|
||||
nRet = ReadNTimeout(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
if( nRet == 0 )
|
||||
{
|
||||
// Remain이 0일 경우가 모두 받은 상황인데, 그것을 알 수 없다면,
|
||||
// Ret==0일 때가 다 준 상황으로 판단해야 하지 않을까? 그렇다면 에러가 아니다.
|
||||
LOG(LDBG, "read socket closed.");
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{ // 단순 소켓 에러.
|
||||
LOG(LERR, "read socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -2 )
|
||||
{ // 타임아웃.
|
||||
LOG(LERR, "read socket timed out.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
// 정상 결과는 아래와 같은 형태이다.
|
||||
//----------------------------------------------------------------
|
||||
// HTTP/1.1 200 OK
|
||||
// Date: Thu, 10 Jun 2010 03:59:23 GMT
|
||||
// Server: Apache/2.0.55 (Unix) DAV/2 PHP/5.2.1
|
||||
// X-Powered-By: PHP/5.2.1
|
||||
// Content-Length: 87
|
||||
// Connection: close
|
||||
// Content-Type: text/html; charset=EUC-KR
|
||||
//
|
||||
// [RAID:qcrts4.ktsh.co.kr]::2010-07-09 12:59:19:Controller#1: SW API Interface API Log In
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// 첫번째 라인만 출력하기 위해서 \n을 \0으로 바꾸고 출력한다.
|
||||
char* pEnd = strchr(szRcvBuffer, '\n');
|
||||
*pEnd = '\0';
|
||||
|
||||
LOG(LINF, "Result:%s", szRcvBuffer);
|
||||
|
||||
// Close()는 return값이 없음.
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
SMS Sender Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/19
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __SMS_SENDER__
|
||||
#define __SMS_SENDER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
#include "BaseSocket.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief CSmsSender
|
||||
/// SmsSender는 지정된 포멧에 따라 php 웹 페이지를 호출한다.
|
||||
///
|
||||
class CSmsSender : public CBaseSocket
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
/// @param [in] szHost SMS 전송 장비 호스트
|
||||
/// @param [in] nPort SMS 전송 장비 접근 Port
|
||||
/// @param [in] szPath SMS 전송 기능이 구현된 PHP 파일명.
|
||||
CSmsSender(const string& szHost, const int nPort, const string& szPath);
|
||||
|
||||
~CSmsSender();
|
||||
|
||||
/// @brief Init 함수 클래스 환경이 정상적인지를 검사한다.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Init();
|
||||
|
||||
/// @brief PHP Web페이지를 통해 SMS발송 요청을 수행한다.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool CallWebPage();
|
||||
bool SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg);
|
||||
|
||||
private:
|
||||
// 로깅 파일
|
||||
string PostDataEncode(const char *pszCommand, size_t length);
|
||||
string RemoveBlankSpace(const char* pszData, size_t nLength);
|
||||
|
||||
string m_szHost;
|
||||
int m_nPort;
|
||||
string m_szPath;
|
||||
string m_szMessage;
|
||||
string m_szGroupId;
|
||||
};
|
||||
#endif // __SMS_SENDER__
|
||||
@@ -0,0 +1,321 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "UdpListener.h"
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 9216
|
||||
|
||||
#define MaxSizeOfTID 52
|
||||
#define MaxSizeOfIssuer 128
|
||||
#define MaxSizeOfSID 128
|
||||
#define MaxSizeOfRCID 32
|
||||
|
||||
|
||||
int CUdpListener::SendMsg(char * szSndBuffer,int size, struct sockaddr_in * cliaddr, socklen_t nAddrSize)
|
||||
{
|
||||
int SndBlockSize = 8196;
|
||||
char szLineBuffer[SndBlockSize];
|
||||
int nLeft = size;
|
||||
char * pTmp = szSndBuffer;
|
||||
int nWrite = 0;
|
||||
do
|
||||
{
|
||||
int offset = 0;
|
||||
::memset(szLineBuffer, 0, SndBlockSize);
|
||||
if( nLeft < SndBlockSize )
|
||||
SndBlockSize = nLeft;
|
||||
while( offset < SndBlockSize )
|
||||
szLineBuffer[offset++] = *pTmp++;
|
||||
szLineBuffer[offset] = '\0';
|
||||
|
||||
//DEBUG_LOG("LINE : [%s]", szLineBuffer);
|
||||
nWrite = ::sendto(m_nSocket, szLineBuffer, offset + 1, 0, (struct sockaddr *)cliaddr, nAddrSize);
|
||||
if(nWrite < 0)
|
||||
{ // error
|
||||
LOG(LERR, "sendto socket(%d) error (%s)", m_nSocket, strerror(errno));
|
||||
break;
|
||||
}
|
||||
else if(nWrite == 0)
|
||||
{ // socket closed
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LDBG, "SEND MESSAGE %d, %d, %s", nWrite, offset+1, szLineBuffer);
|
||||
}
|
||||
nLeft -= nWrite;
|
||||
} while ( nLeft > 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// @brief 클라이언트로 부터 받아온 스트링 프로토콜을 정수 프로토콜로 변환한다.
|
||||
/// @param [in] szProtocol 클라이언트로부터 전송받은 스트링 프로토콜.
|
||||
/// @return 성공: 양의 정수의 프로토콜 값. 실패: -1
|
||||
int CUdpListener::ParsingPacket(const char * szProtocol)
|
||||
{
|
||||
int nRet = -1;
|
||||
|
||||
if( szProtocol == NULL )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 구버전 프로토콜을 유지한다.
|
||||
if(strcmp(szProtocol, "I'M YOUR FATHER. BASTARD !") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- (OLD)CMD_EVENT_INFO_ONE Called!-----------");
|
||||
nRet = CMD_EVENT_INFO_ONE;
|
||||
}
|
||||
else if(strcmp(szProtocol, "I'M YOUR GOD. BASTARD !") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- (OLD)CMD_EVENT_INFO_ALL Called! ---------");
|
||||
nRet = CMD_EVENT_INFO_ALL;
|
||||
}
|
||||
else if(strcmp(szProtocol, "EVENT:INFO:ONE") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- CMD_EVENT_INFO_ONE Called!-----------");
|
||||
nRet = CMD_EVENT_INFO_ONE;
|
||||
}
|
||||
else if(strcmp(szProtocol, "EVENT:INFO:ALL") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- CMD_EVENT_INFO_ALL Called! ---------");
|
||||
nRet = CMD_EVENT_INFO_ALL;
|
||||
}
|
||||
// 프로토콜을 추가하려면 여기에 아래의 형태로 추가한다.
|
||||
// else if(strcmp(szProtocol, "String...........") == 0)
|
||||
// {
|
||||
// nRet = CMD_XXXXXXXXX;
|
||||
// }
|
||||
else // Invalid Protocol
|
||||
{
|
||||
nRet = CMD_UDP_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
|
||||
CUdpListener::CUdpListener(CEventDataManager* pEventDataManager)
|
||||
: m_pEventDataManager( pEventDataManager )
|
||||
{
|
||||
m_nSocket = -1;
|
||||
LOG(LDBG, "Constructor has been called.");
|
||||
}
|
||||
|
||||
CUdpListener::~CUdpListener()
|
||||
{
|
||||
if ( m_nSocket != -1)
|
||||
{
|
||||
::close(m_nSocket);
|
||||
m_nSocket = -1;
|
||||
}
|
||||
pthread_cancel(m_threadHandle);
|
||||
}
|
||||
|
||||
bool CUdpListener::Init(int nPort)
|
||||
{
|
||||
LOG(LDBG, "Initializer has been called.");
|
||||
int fRet = 0;
|
||||
struct sockaddr_in SocAddr;
|
||||
int nVal=1;
|
||||
|
||||
if(m_pEventDataManager == NULL )
|
||||
{
|
||||
LOG(LERR, "Invalid Object.");
|
||||
return false;
|
||||
}
|
||||
if( nPort <= 0 )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter. Port=%d", nPort);
|
||||
return false;
|
||||
}
|
||||
SocAddr.sin_family = AF_INET;
|
||||
SocAddr.sin_port = htons(nPort);
|
||||
SocAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// UDP 소켓 생성.
|
||||
m_nSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (m_nSocket < 0)
|
||||
{
|
||||
LOG(LERR, "Socket Create: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&nVal, sizeof(int)) < 0)
|
||||
{
|
||||
LOG(LERR, "setsockopt(SO_REUSEADDR) failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// UDP 소켓 바인드.
|
||||
fRet = ::bind(m_nSocket, (struct sockaddr *)&SocAddr, sizeof(SocAddr));
|
||||
if (fRet != 0)
|
||||
{
|
||||
LOG(LERR, "Socket Bind: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(LDBG, "Initializer has been succeed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///@brief 이 함수에서 UDP 통신을 receive 한다.
|
||||
void CUdpListener::Execute()
|
||||
{
|
||||
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
|
||||
char szSndBuffer[DEFAULT_BUFFER_SIZE];
|
||||
int nRead = 0;
|
||||
struct sockaddr_in cliaddr;
|
||||
int addr_len = sizeof(cliaddr);
|
||||
int bMode = 0;
|
||||
int nRet = -1;
|
||||
bool bRet = false;
|
||||
string szTmp;
|
||||
|
||||
::memset(szRcvBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
::memset(szSndBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
//DEBUG_LOG("DEBUG: %d , %lu %lu, %lu", m_nSocket, szRcvBuffer, &cliaddr, &addr_len);
|
||||
nRead = ::recvfrom(m_nSocket, (char *)&szRcvBuffer, (unsigned int)DEFAULT_BUFFER_SIZE, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&addr_len);
|
||||
if ( nRead <= 0 )
|
||||
{
|
||||
LOG(LERR, "recvfrom() error. %s.",strerror(errno));
|
||||
return;
|
||||
}
|
||||
LOG(LDBG, "Request Buffer = %s", szRcvBuffer);
|
||||
LOG(LDBG, "From = %s", inet_ntoa(cliaddr.sin_addr));
|
||||
|
||||
|
||||
bMode = ParsingPacket(szRcvBuffer);
|
||||
|
||||
switch (bMode)
|
||||
{
|
||||
case CMD_EVENT_INFO_ONE:
|
||||
{
|
||||
CEventData resData;
|
||||
|
||||
nRet = m_pEventDataManager->GetLatestData(resData);
|
||||
if ( nRet == -1 )
|
||||
{
|
||||
LOG(LERR, "GeLatestData() failed.");
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "1:%ld:Initializing Now.", ::time(NULL));
|
||||
} else
|
||||
{
|
||||
if( nRet == 0 )
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:%s", nRet,::time(NULL), resData.m_szEventData.c_str());
|
||||
else
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:%s", nRet,::time(NULL), resData.m_szEventData.c_str());
|
||||
}
|
||||
// 클라이언트 메시지 송신
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
LOG(LDBG, "SEND MESSAGE %s.", szSndBuffer);
|
||||
}
|
||||
break;
|
||||
case CMD_EVENT_INFO_ALL:
|
||||
{
|
||||
list<CEventData> listRet;
|
||||
listRet.clear();
|
||||
|
||||
bRet = m_pEventDataManager->GetAllData(listRet);
|
||||
if( nRet == false || listRet.empty() )
|
||||
{
|
||||
LOG(LERR, "GetAllData() failed.");
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:No EVENT IS FOUND.", 1,(long)::time(NULL));
|
||||
} else
|
||||
{
|
||||
// 2013-10-17
|
||||
// 기존에는 모든 메세지를 보냈으나, sms메세지를 만들어주는 web page에서 처리가안되는것을 확인했다.
|
||||
// 이에 따라 최근 100개 메세지를 전송하는 것으로 처리한다.
|
||||
//for (list<CEventData>::iterator it = listRet.begin(); it != listRet.end(); it++)
|
||||
int nCount = 0;
|
||||
|
||||
for (list<CEventData>::reverse_iterator it = listRet.rbegin(); it != listRet.rend(); it++)
|
||||
{
|
||||
// 2016.01.22 dadamin
|
||||
// 96 => 1024 : buffer overflow 발생하여 메세지 전송 실패 발생하여 변경함
|
||||
char timeBuf[1024] = {0};
|
||||
tm* ptm = localtime(&it->m_evtTime);
|
||||
::sprintf(timeBuf, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
|
||||
ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
|
||||
it->m_szEventData.c_str());
|
||||
szTmp += timeBuf;
|
||||
nCount++;
|
||||
|
||||
if( nCount >= 100 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// upd send size limit
|
||||
if(szTmp.length() > 1100 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// upd send size limit
|
||||
::snprintf(szSndBuffer, 1400, "%d:%ld:%s", 1,(long)::time(NULL) , szTmp.c_str());
|
||||
}
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
LOG(LDBG, "SEND MESSAGE %s.", szSndBuffer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LDBG, "----------------- INVALID COMMAND REQUEST!!! ----------------------------------");
|
||||
LOG(LERR, "Invalid Protocol.");
|
||||
::memset(szSndBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "1:%ld:Invalid Arguments!", (long)::time(NULL));
|
||||
|
||||
LOG(LDBG, "SENDING Buffer = [%s]", szSndBuffer);
|
||||
|
||||
//::sendto(m_nSocket, szSndBuffer, strlen(szSndBuffer), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
// TODO: error check
|
||||
return;
|
||||
break;
|
||||
}//~switch (bMode)
|
||||
}
|
||||
|
||||
|
||||
void* CUdpListener::EntryPoint(void* arg)
|
||||
{
|
||||
CUdpListener* pObject = reinterpret_cast<CUdpListener *>(arg);
|
||||
if( pObject == NULL )
|
||||
{
|
||||
// static Function이기 때문에 로깅할 수 없다...
|
||||
//ERROR_LOG("Critical Memory Error, Invalid Object.");
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
pthread_detach( pthread_self() );
|
||||
|
||||
while(1)
|
||||
{
|
||||
pthread_testcancel();
|
||||
pObject->Execute();
|
||||
pthread_testcancel();
|
||||
}
|
||||
|
||||
// pthread_exit();
|
||||
return (void *)NULL;
|
||||
}
|
||||
|
||||
bool CUdpListener::Start()
|
||||
{
|
||||
int nRet = ::pthread_create(&m_threadHandle, 0, CUdpListener::EntryPoint, this);
|
||||
|
||||
if( nRet != 0 )
|
||||
{
|
||||
LOG(LERR, "Thread create failed: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
LOG(LDBG, "Thread create succeed.");
|
||||
sleep(0);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
UDP Listener Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/17
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __UDP_LISTENER__
|
||||
#define __UDP_LISTENER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
#include "EventDataManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief Protocols
|
||||
#define CMD_UDP_BASE 1000
|
||||
#define CMD_UDP_ERROR CMD_UDP_BASE
|
||||
#define CMD_EVENT_INFO_ONE ( CMD_UDP_BASE + 101 )
|
||||
#define CMD_EVENT_INFO_ALL ( CMD_UDP_BASE + 102 )
|
||||
|
||||
/// @brief CUdpListener
|
||||
/// UdpListener 는 client에서 udp 요청되는 패킷을 수신해서 관리하게 되며,
|
||||
/// raid 정보 조회 후, 결과를 전송한다.
|
||||
/// 내부적으로 Thread를 사용하고있다.
|
||||
class CUdpListener
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
/// @param [in] pEventManager CEventManager 객체
|
||||
CUdpListener(CEventDataManager* pEventDataManager);
|
||||
~CUdpListener();
|
||||
|
||||
/// @brief Init 함수 클래스 환경이 정상적인지를 검사한다.
|
||||
/// @param [in] nPort UDP listen port 번호.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Init(int nPort);
|
||||
|
||||
/// @brief Thread를 생성하고, 이를 시작한다.
|
||||
/// @param none
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Start();
|
||||
|
||||
private:
|
||||
// 이벤트 저장 객체
|
||||
CEventDataManager* m_pEventDataManager;
|
||||
|
||||
// 쓰레드 핸들
|
||||
pthread_t m_threadHandle;
|
||||
|
||||
// 쓰레드 시작 루틴이다.
|
||||
static void* EntryPoint(void* arg);
|
||||
|
||||
int m_nSocket;
|
||||
|
||||
// 해당 함수의 내용은 수정하지 말것.
|
||||
void Execute();
|
||||
|
||||
|
||||
/// @brief 클라이언트로 부터 받아온 스트링 프로토콜을 정수 프로토콜로 변환한다.
|
||||
/// @param [in] szProtocol 클라이언트로부터 전송받은 스트링 프로토콜.
|
||||
/// @return 성공: 양의 정수의 프로토콜 값. 실패: -1
|
||||
int ParsingPacket(const char * szProtocol);
|
||||
int SendMsg(char * szSndBuffer,int size, struct sockaddr_in * cliaddr, socklen_t nAddrSize);
|
||||
CEventData m_evtData;
|
||||
};
|
||||
#endif // __UDP_LISTENER__
|
||||
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
fhs_raidmond Header ( fhs_raidmond.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/09
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __FHS_RAIDMOND_GLOBAL_VALUE_H__
|
||||
#define __FHS_RAIDMOND_GLOBAL_VALUE_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
struct st_config
|
||||
{
|
||||
// Common Part
|
||||
std::string szLogDir;
|
||||
int nLogLevel;
|
||||
|
||||
// fhs_raidmond Part
|
||||
int nCheckTerm;
|
||||
|
||||
int nReportPort;
|
||||
|
||||
int nEventLevel;
|
||||
|
||||
std::string szSMSHost;
|
||||
int nSMSPort;
|
||||
std::string szSMSSendfile;
|
||||
|
||||
|
||||
// »ý¼ºÀÚ
|
||||
st_config()
|
||||
{
|
||||
nLogLevel = 0;
|
||||
nCheckTerm = 0;
|
||||
nReportPort = 0;
|
||||
nEventLevel = 0;
|
||||
nSMSPort = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief Global config object.
|
||||
extern struct st_config g_envConfig;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FHS_RAIDMOND_GLOBAL_VALUE_H__ */
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "GetConfig.h"
|
||||
#include "Child.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/// config object initialize
|
||||
struct st_config g_envConfig;
|
||||
|
||||
/// daemon flag
|
||||
static bool _isdaemon = true;
|
||||
|
||||
/// @brief Program version 출력 함수.
|
||||
/// @return void
|
||||
static void ShowVersion(void)
|
||||
{
|
||||
cerr << "[info] " << PROG_NAME << " Version :" << PROG_VERSION << endl;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Program version 사용 방법 출력 함수.
|
||||
/// @return void
|
||||
static void ShowUsages(void)
|
||||
{
|
||||
ShowVersion();
|
||||
cerr << "usage: " << PROG_NAME << " [-vhcD]" << endl;
|
||||
cerr << "options are: " << endl;
|
||||
cerr << "-v : print current version" << endl;
|
||||
cerr << "-c <path> : Log Diretory" << endl;
|
||||
cerr << "-D : running console mode" << endl;
|
||||
cerr << "-h : help " << endl;
|
||||
}
|
||||
|
||||
/// @brief Child 프로세스 생성(fork) 함수
|
||||
/// @return void
|
||||
static void MakeChild(void)
|
||||
{
|
||||
pid_t processId;
|
||||
// Child 프로세스 fork
|
||||
processId = fork();
|
||||
if( processId < 0 ) // Fork fail
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG(LERR, "Child Process create failed. [%d][%s]", errorNum, strerror(errorNum) );
|
||||
return;
|
||||
}
|
||||
else if( processId == 0 ) // Parent Process => Child Process
|
||||
{
|
||||
// Child Process Main 함수 호출 및 종료처리.
|
||||
ChildMain();
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parent Process => Logging
|
||||
_LOG(LNOT, "Child Process create success. PID[%d]" , processId);
|
||||
// 잠시 대기
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Parent Process 에서 child Process 가 종료된 경우 시그널 처리를 위한 함수
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void sigchld_hdl( int nSignalNumber )
|
||||
{
|
||||
pid_t killPid;
|
||||
int nKillStatus;
|
||||
while( ( killPid = waitpid( -1, &nKillStatus, WNOHANG ) ) > 0 )
|
||||
{
|
||||
// 자식 프로세스가 Signal 에 의해 종료되었는지 검사.
|
||||
if( WIFSIGNALED( nKillStatus ) )
|
||||
{
|
||||
LOG(LWAR, "Child process[%d] killed by signal[%d]", killPid, WTERMSIG( nKillStatus ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LWAR, "Child process[%d] killed. Not signal", killPid );
|
||||
// Child 프로세스가 EXIT_FAILURE 반환 ( 초기화 실패시 )
|
||||
// 해당 내역을 화면 및 로그 상에 출력하고
|
||||
// 자식 프로세스를 재생성 처리하지 않는다.
|
||||
if( WIFEXITED( nKillStatus ) )
|
||||
{
|
||||
if( WEXITSTATUS( nKillStatus ) == EXIT_FAILURE )
|
||||
{
|
||||
LOG(LERR, "Child Process[%d] initilaize failed.", killPid );
|
||||
LOG(LERR, "Parent Process[%d] exit by Child. Good Bye..", getpid());
|
||||
cerr << "[error] " << PROG_NAME << ": Process exit by Child process initialize failed. check log file." << endl;
|
||||
usleep(500000);
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Child Process 재생성 처리.
|
||||
MakeChild();
|
||||
}
|
||||
// 오류 발생시 해당 내역 로깅
|
||||
if( killPid < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG(LERR, "Parent process error: SIG_CHLD receive but waitpid return error[%d][%s]", errorNum, strerror(errorNum));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// @brief Parent Process 종료 Signal 을 전달받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigTermParent( int nSignalNumber )
|
||||
{
|
||||
// Signal Number 에 따른 로깅처리.
|
||||
if( nSignalNumber == SIGTERM )
|
||||
{
|
||||
LOG(LWAR, "Parent Process[%d] exit job start by user signal [SIGTERM]", getpid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LWAR, "Parent Process[%d] exit job start by abnormal signal [%d]", getpid(), nSignalNumber );
|
||||
}
|
||||
// Process 종료관련 작업 추가
|
||||
LOG(LWAR, "Parent Process[%d] exit job end. Good Bye..", getpid());
|
||||
// KILL - Child
|
||||
kill(0, SIGTERM);
|
||||
// waitpid
|
||||
while(waitpid(-1, NULL, WNOHANG) > 0);
|
||||
|
||||
usleep(500000);
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
/// @brief Parent Process 에서 Core 생성 관련 Signal 을 받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigCoreParent( int nSignalNumber )
|
||||
{
|
||||
LOG(LERR, "Parent Process[%d] abnoraml exit. Check Core file. Receive signal [%d]", getpid(), nSignalNumber );
|
||||
//LOG(LERR, "Core file path : [%s/%s.core]", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
// Process 종료관련 작업 추가
|
||||
|
||||
// Log Directory 상에 Core 파일 생성처리.
|
||||
chdir( g_envConfig.szLogDir.c_str() );
|
||||
signal( nSignalNumber, SIG_DFL );
|
||||
// Core dump 생성을 위한 신호 발생처리.=> ?
|
||||
raise( nSignalNumber );
|
||||
}
|
||||
|
||||
/// @brief Parent 프로세스 signal 처리 설정을 위한 함수
|
||||
/// @return void
|
||||
static void SetSignalParent()
|
||||
{
|
||||
sigset_t set;
|
||||
struct sigaction act;
|
||||
sigfillset( &set );
|
||||
sigprocmask( SIG_SETMASK, &set, NULL );
|
||||
memset( &act, 0x00, sizeof(act) );
|
||||
sigfillset( &act.sa_mask );
|
||||
/* 무시할 신호 목록 */
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction( SIGPIPE, &act, NULL); /* 파이프 디스크립터 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정 */
|
||||
sigaction( SIGHUP , &act, NULL); /* Process를 기동시킨 관리자의 로그아웃시 발생 시그널 */
|
||||
sigaction( SIGQUIT, &act, NULL); /* 키보드에 의한 Abort 신호 처리 => ? */
|
||||
|
||||
if(_isdaemon)
|
||||
{
|
||||
sigaction( SIGINT , &act, NULL); /* ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음 */
|
||||
}
|
||||
else
|
||||
{
|
||||
act.sa_handler = SigTermParent;
|
||||
sigaction( SIGINT, &act, NULL); /* ^C 키를 누른 경우 받는 신호 => kill -TERM 과 동일한 처리함 */
|
||||
}
|
||||
|
||||
// Child Process 종료에 대한 처리기 설정.
|
||||
act.sa_handler = sigchld_hdl;
|
||||
sigaction( SIGCHLD, &act, NULL);
|
||||
/* 각종 에러나 사용자의 종료 신호 처리 */
|
||||
act.sa_handler = SigTermParent;
|
||||
sigaction( SIGTERM, &act, NULL); /* kill -TERM 에 의한 프로세스 종료시 */
|
||||
/* Core 관련 signal 처리 : 오류 처리 및 Debug(core dump) 목적 */
|
||||
// dadamin : 팀 기준 적용
|
||||
//act.sa_handler = SigCoreParent;
|
||||
//sigaction( SIGILL , &act, NULL); /* Illegal instruction */
|
||||
//sigaction( SIGFPE , &act, NULL); /* Erroneout arithmetic operation */
|
||||
//sigaction( SIGBUS , &act, NULL); /* Access to undefined portion of a memory object */
|
||||
//sigaction( SIGSEGV, &act, NULL); /* Invalid memory reference */
|
||||
//sigaction( SIGSYS , &act, NULL); /* Bad System Call */
|
||||
//sigaction( SIGXCPU, &act, NULL); /* CPU-time limit exceeded */
|
||||
//sigaction( SIGXFSZ, &act, NULL); /* File-size limit exceeded */
|
||||
sigemptyset(&set); /* 신호 처리기 처리 설정 위한 블록 해제 */
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
}
|
||||
// daemon 생성 함수
|
||||
static bool daemon_create(bool bcreate)
|
||||
{
|
||||
// set parent signal
|
||||
SetSignalParent();
|
||||
|
||||
// set mask
|
||||
umask(0);
|
||||
|
||||
// daemon
|
||||
if(bcreate && daemon(false, false) != 0 ) // after this line, parent's pid will be changed.
|
||||
{
|
||||
cerr << "[error] Daemonize Failed.(errno : " << errno << ")" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/// @brief std 상에 trim 함수가 없어서 직접 구현 아니면 boost/algorithm/string.hpp 상의 boost::trim 함수 사용
|
||||
/// @return void
|
||||
static void Trim( string & str )
|
||||
{
|
||||
if( str.length() == 0 )
|
||||
return ;
|
||||
// 문자열 뒤의 공백, TAB, CR 등의 문자 제거처리.
|
||||
string::size_type pos = str.find_last_not_of(" \a\b\f\n\r\t\v");
|
||||
if( pos != string::npos )
|
||||
str.erase( pos + 1 );
|
||||
// 문자열 앞의 공백, TAB, CR 등의 문자 제거처리.
|
||||
pos = str.find_first_not_of(" \a\b\f\n\r\t\v");
|
||||
if( pos != string::npos )
|
||||
str.erase( 0, pos );
|
||||
}
|
||||
/// @brief 현재 Process가 기동중인지 여부를 판단하기 위한 함수( 프로세스 중복 실행 체크)
|
||||
/// @return 이미 해당 프로세스가 기동 중인 경우 true 반환, 그렇지 않으면 false 반환.
|
||||
static bool IsCurrentProcessRun()
|
||||
{
|
||||
char tempBuffer[512];
|
||||
FILE * fd = NULL;
|
||||
bool bRun = false;
|
||||
snprintf( tempBuffer, sizeof(tempBuffer), "pgrep -x %s | sort", PROG_NAME );
|
||||
fd = popen( tempBuffer, "r" );
|
||||
if( fd == NULL )
|
||||
{
|
||||
cerr << "[error] Process duplication check failed.[popen error][" << strerror(errno) << "]" << endl;
|
||||
// 오류 발생시 true 반환하여 프로세스 실행 방지처리
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( tempBuffer, 0x00, sizeof(tempBuffer) );
|
||||
while( fgets( tempBuffer, sizeof(tempBuffer)-1, fd) != NULL )
|
||||
{
|
||||
string tempPid( tempBuffer );
|
||||
Trim(tempPid);
|
||||
if( atoi( tempPid.c_str() ) != getpid() )
|
||||
{
|
||||
cout << "[info] Process duplication found. pid[" << atoi( tempPid.c_str() ) << "]" << endl;
|
||||
bRun = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pclose( fd );
|
||||
return bRun;
|
||||
}
|
||||
}
|
||||
// main function
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
string cofigpath = DEFAULT_CONFIG_FILE;
|
||||
// parse command line arguments
|
||||
int o;
|
||||
while ((o = getopt(argc, argv, "vhDc:")) >= 0)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case 'h': // help
|
||||
ShowUsages();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
case 'v': // version
|
||||
ShowVersion();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
case 'D': // consol mode
|
||||
_isdaemon = false;
|
||||
cerr << "Runnig Console mode." << endl;
|
||||
break;
|
||||
case 'c': // config file
|
||||
cofigpath = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 프로그램 중복 실행 체크
|
||||
if( IsCurrentProcessRun() == true )
|
||||
{
|
||||
cerr << "[warning] Process[" << PROG_NAME << "] is already running...." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// load config
|
||||
string szErrorMessage;
|
||||
if(!GetConfig( cofigpath, g_envConfig, szErrorMessage ) )
|
||||
{
|
||||
cerr << "[error] Process[" << PROG_NAME << "]: " << szErrorMessage << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// init log
|
||||
if( CLogger::Init( PROG_NAME, g_envConfig.szLogDir.c_str(), g_envConfig.nLogLevel ) == false )
|
||||
{
|
||||
cerr << "[error] Process[" << PROG_NAME << "]: Log init failed." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Global log object set
|
||||
|
||||
// daemon create
|
||||
if(!daemon_create(_isdaemon))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
// Process 기동 관련 정보 로깅
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
_LOG(LINF, " %s (FHS RAID Monitor Daemon) Start. Version: %s", PROG_NAME, PROG_VERSION );
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
_LOG(LINF, "Config file : %s", cofigpath.c_str() );
|
||||
_LOG(LINF, "Log Path : %s/%s", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
_LOG(LINF, "Logging Level : %d", g_envConfig.nLogLevel );
|
||||
_LOG(LINF, "health check term : %d", g_envConfig.nCheckTerm );
|
||||
_LOG(LINF, "report thread port : %d", g_envConfig.nReportPort );
|
||||
_LOG(LINF, "event level : %d", g_envConfig.nEventLevel );
|
||||
_LOG(LINF, "sms send host : %s", g_envConfig.szSMSHost.c_str() );
|
||||
_LOG(LINF, "sms send port : %d", g_envConfig.nSMSPort);
|
||||
_LOG(LINF, "sms send file : %s", g_envConfig.szSMSSendfile.c_str() );
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
|
||||
// fork child
|
||||
MakeChild();
|
||||
|
||||
// set process title
|
||||
#if defined(__FreeBSD__)
|
||||
setproctitle( "Parent [monitor Child process]" );
|
||||
#endif
|
||||
// wait
|
||||
while( 1 )
|
||||
{
|
||||
pause();
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user