This commit is contained in:
biosvos
2026-08-07 17:38:18 +09:00
commit 873193a243
9613 changed files with 2755992 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
/***************************************************************************
Argument Parser Class (ArgParser.cpp)
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "ArgParser.h"
CArgParser::CArgParser(int argc, char** argv)
{
for (int i=1; i<argc; i++)
{
#ifdef _DEBUG
cout << "arg i = " << i << "," << argv[i] << endl;
#endif // _DEBUG
m_args.push_back(argv[i]);
}
}
CArgParser::~CArgParser()
{
m_args.clear();
}
void CArgParser::dashes2underscores(const char *input, char *output)
{
char c = 0;
char *o = output;
const char *i = input;
// first two characters are copied as-is
*o = *i++;
if (*o++ == '\0')
return;
*o = *i++;
if (*o++ == '\0')
return;
for (; ((c = *i)); ++i)
{
if (c == '=')
{
strcpy(o, i);
return;
}
if (c == '-')
*o++ = '_';
else
*o++ = c;
}
*o++ = '\0';
}
bool CArgParser::parsewitharg(vector<char*>::iterator &i, std::string *ret, va_list ap)
{
const char *first = *i;
char tmp[strlen(first)+1];
dashes2underscores(first, tmp);
first = tmp;
const char *a;
int strlen_a;
// does this argument match any of the possibilities?
while (1)
{
a = va_arg(ap, char*);
if (a == NULL)
return false;
strlen_a = strlen(a);
char a2[strlen_a+1];
dashes2underscores(a, a2);
if (strncmp(a2, first, strlen(a2)) == 0)
{
if (first[strlen_a] == '=')
{
*ret = first + strlen_a + 1;
i = m_args.erase(i);
return true;
}
else if (first[strlen_a] == '\0')
{
// find second part (or not)
if (i+1 == m_args.end())
{
cerr << "[error] Option " << *i << " requires an argument." << std::endl;
_exit(EXIT_FAILURE);
}
i = m_args.erase(i);
*ret = *i;
i = m_args.erase(i);
return true;
}
}
}
return false;
}
bool CArgParser::argparseflag(vector<char*>::iterator &i, ...)
{
const char *first = *i;
char tmp[strlen(first)+1];
dashes2underscores(first, tmp);
first = tmp;
const char *a;
va_list ap;
va_start(ap, i);
while (1)
{
a = va_arg(ap, char*);
if (a == NULL)
{
va_end(ap);
return false;
}
char a2[strlen(a)+1];
dashes2underscores(a, a2);
if (strcmp(a2, first) == 0)
{
i = m_args.erase(i);
va_end(ap);
return true;
}
}
return false;
}
bool CArgParser::argparsewitharg(vector<char*>::iterator &i, string *ret, ...)
{
bool r;
va_list ap;
va_start(ap, ret);
r = parsewitharg(i, ret, ap);
va_end(ap);
return r;
}
bool CArgParser::checkvalue(const char *c, string *ret/* = NULL*/)
{
for (vector<char*>::iterator i = m_args.begin(); i != m_args.end(); ++i)
{
if(ret)
{
if(argparsewitharg(i,ret, c, (char*)NULL))
return true;
}
else
{
if(argparseflag(i,c, (char*)NULL))
return true;
}
}
return false;
}
+40
View File
@@ -0,0 +1,40 @@
/***************************************************************************
Argument Parser Class Header ( ArgParser.h )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __ARGUMENT_PARSER_H__
#define __ARGUMENT_PARSER_H__
class CArgParser
{
public:
CArgParser(int argc, char** argv);
~CArgParser();
bool argparseflag(vector<char*>::iterator &i, ...);
bool argparsewitharg(vector<char*>::iterator &i, string *ret, ...);
bool checkvalue(const char *c, string *ret = NULL);
inline bool empty() { return m_args.empty(); }
protected:
void dashes2underscores(const char *input, char *output);
bool parsewitharg(vector<char*>::iterator &i, std::string *ret, va_list ap);
private:
vector<char*> m_args;
};
#endif // __ARGUMENT_PARSER_H__
+359
View File
@@ -0,0 +1,359 @@
/***************************************************************************
Config Class (Config.cpp)
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Configs.h"
#include "Config.h"
CMyConfig *CMyConfig::m_pInstance = NULL;
void StringSplit(string str, string delim, vector<string> &results, bool bUseEmpty /*= false*/)
{
const string strEmpty("");
string::size_type cutAt;
while( (cutAt = str.find_first_of(delim)) != str.npos )
{
if(cutAt > 0)
{
results.push_back(str.substr(0,cutAt));
}
else
{
if(bUseEmpty && cutAt == 0)
results.push_back(strEmpty);
}
str = str.substr(cutAt+1);
}
if(str.length() > 0)
{
results.push_back(str);
}
}
CCommonConfig::CCommonConfig( string szFilename, string szProgramName )
: m_szConfigFile(szFilename), m_szProgramName(szProgramName), m_nLogLevel(0)
{
}
CCommonConfig::~CCommonConfig()
{
}
bool CCommonConfig::LoadConf()
{
#ifdef _DEBUG
cout << "CCommonConfig::LoadConf() =>" << endl;
#endif // _DEBUG
string szValue;
// Config 처리를 위한 객체 생성
Config conf;
// Config File open
if( conf.Open( m_szConfigFile ) == false )
{
m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
return false;
}
// log path
if( conf.GetConfig( "COMMON", "DEFAULT_LOG_DIR", szValue ) )
{
m_szAppLogRoot = szValue;
}
// log level
if( conf.GetConfig( "COMMON", "LOG_LEVEL", szValue ) )
{
m_nLogLevel = atoi( szValue.c_str() );
}
#ifdef _DEBUG
PrintValue();
#endif // _DEBUG
return true;
}
bool CCommonConfig::CheckValue()
{
if(m_szAppLogRoot.empty())
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->DEFAULT_LOG_DIR";
return false;
}
if( m_nLogLevel <= 0)
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->LOG_LEVEL";
return false;
}
return true;
}
void CCommonConfig::PrintValue()
{
cout << "Log Value : " << m_szAppLogRoot << "," << m_nLogLevel << endl;
}
CMyConfig::CMyConfig( string szFilename, string szProgramName)
: CCommonConfig(szFilename, szProgramName)
, m_TcpListenPort(0), m_WorkProcessCnt(0), m_WorkThreadCnt(1000)
{
}
CMyConfig::~CMyConfig()
{
}
bool CMyConfig::LoadConf()
{
if( CCommonConfig::LoadConf() == false)
return false;
#ifdef _DEBUG
cout << "CMyConfig::LoadConf() =>" << endl;
#endif // _DEBUG
string szValue;
// Config 처리를 위한 객체 생성
Config conf;
// Config File open
if( conf.Open( m_szConfigFile ) == false )
{
m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
return false;
}
// Config File open
if( conf.GetConfig( m_szProgramName, "DEFAULT_LOG_DIR", szValue ) )
{
m_szAppLogRoot = szValue;
}
// log level
if( conf.GetConfig( m_szProgramName, "LOG_LEVEL", szValue ) )
{
m_nLogLevel = atoi( szValue.c_str() );
}
// TCP Listen Port
if(conf.GetConfig( m_szProgramName, "TCP_LISTEN_PORT", szValue ))
{
m_TcpListenPort = atoi( szValue.c_str() );
}
// Work Process Count
if(conf.GetConfig( m_szProgramName, "WORK_PROCESS_CNT", szValue ))
{
m_WorkProcessCnt = atoi( szValue.c_str() );
}
// Work Thread Pool Count
if(conf.GetConfig( m_szProgramName, "WORK_THREAD_POOL", szValue ))
{
m_WorkThreadCnt = atoi( szValue.c_str() );
}
// Used DataBase Type
//string k = "=";
//conf.SetDelimiter()
if(conf.GetConfig(m_szProgramName, "USED_DATABASE_TYPE", m_usedDBTypeVec))
{
}
// Database info
for (vector<string>::iterator it = m_usedDBTypeVec.begin() ; it != m_usedDBTypeVec.end(); ++it)
{
vector< string > vec;
string t;
t.append(*it);
t.append("_DB_INFO");
#ifdef _DEBUG
cout << " "<<t ;
#endif // _DEBUG
conf.GetConfig(m_szProgramName, t, vec);
#ifdef _DEBUG
cout << ",size(" << vec.size() << ")" << endl ;
#endif // _DEBUG
map<string, CDataBaseInfo> infos;
for (vector<string>::iterator it2 = vec.begin() ; it2 != vec.end(); ++it2)
{
#ifdef _DEBUG
cout << " " << *it2 << endl ;
#endif // _DEBUG
vector< string > vec2;
StringSplit(*it2, "|", vec2, true);
if( vec2.size() < 3 )
{
cerr << "Configuration file is wrong." << endl ;
continue;
}
CDataBaseInfo info;
info.m_poolcnt = atoi(vec2[1].c_str());
info.m_connstr = vec2[2];
pair< map<string, CDataBaseInfo>::iterator, bool > r;
r = infos.insert(make_pair(vec2[0], info));
if(r.second == false)
{
cerr << "Configuration file is error. ["<< t << "] is duplicated.("
<< vec2[0] << ")" << endl ;
return false;
}
}
if(infos.size())
m_DBInfoMap.insert(make_pair(*it, infos));
}
#ifdef _DEBUG
PrintValue();
#endif // _DEBUG
return true;
}
bool CMyConfig::CheckValue()
{
if( CCommonConfig::CheckValue() )
{
if( m_TcpListenPort <= 0)
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + "]->TCP_LISTEN_PORT";
return false;
}
if( m_WorkProcessCnt <= 0)
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + "]->WORK_PROCESS_CNT";
return false;
}
if( m_WorkThreadCnt <= 0)
{
// 해당 값은 gts.conf에 숨기기 위해서 값이 없을 시 무시
//m_szErrMessage = "Config info get failed. [" + m_szProgramName + "]->WORK_THREAD_POOL ";
//return false;
}
if(m_usedDBTypeVec.size() <= 0)
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + "]->USED_DATABASE_TYPE";
return false;
}
for (vector<string>::iterator it = m_usedDBTypeVec.begin() ; it != m_usedDBTypeVec.end(); ++it)
{
map<string, map<string, CDataBaseInfo> >::iterator mitFind;
mitFind = m_DBInfoMap.find(*it);
if(mitFind == m_DBInfoMap.end() || mitFind->second.size() <= 0)
{
m_szErrMessage = "Config info get failed. [" + m_szProgramName + "]->"+ *it + "_DB_INFO";
return false;
}
}
return true;
}
else
{
return false;
}
return true;
}
bool CMyConfig::FindUsedDBType(string &k)
{
// find
vector<string>::iterator i =
find(m_usedDBTypeVec.begin(), m_usedDBTypeVec.end(), k);
if (i!= m_usedDBTypeVec.end())
{
// found it
return true;
}
else
{
// doesn't exist
return false;
}
return true;
}
void CMyConfig::PrintValue()
{
CCommonConfig::PrintValue();
cout << "TCP Listen Port :" << m_TcpListenPort << endl;
cout << "Work Process Count :" << m_WorkProcessCnt << endl;
cout << "Work Thread Count :" << m_WorkThreadCnt << endl;
cout << "Used Database Type : size(" << m_usedDBTypeVec.size() << ")" << endl;
for (vector<string>::iterator it = m_usedDBTypeVec.begin() ; it != m_usedDBTypeVec.end(); ++it)
{
cout << " " << *it << endl;
}
cout << "Database info : size(" << m_DBInfoMap.size() << ")" << endl;
for (map<string, map<string, CDataBaseInfo> >::iterator iter = m_DBInfoMap.begin() ; iter != m_DBInfoMap.end(); ++iter)
{
cout << " " << iter->first << endl;
for( map<string, CDataBaseInfo>::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2)
{
cout << " " << iter2->first << ","<< iter2->second.m_poolcnt << "," << iter2->second.m_connstr << endl;
}
}
}
void CMyConfig::SetFailLogPath(string & path)
{
m_FailLogPath = path;
// 디렉토리 가 존재하지 않는 경우 디렉토리 생성 시도
string cmd = "mkdir -p " + path;
system( cmd.c_str() );
}
bool CMyConfig::Init( string szProgramName, string szFilename )
{
if( CMyConfig::m_pInstance == NULL )
{
CMyConfig::m_pInstance = new CMyConfig(szFilename, szProgramName);
}
return true;
}
void CMyConfig::Exit()
{
if( CMyConfig::m_pInstance != NULL )
{
delete CMyConfig::m_pInstance;
CMyConfig::m_pInstance = NULL;
}
}
CMyConfig* CMyConfig::GetInstance()
{
return CMyConfig::m_pInstance;
}
+109
View File
@@ -0,0 +1,109 @@
/***************************************************************************
Config Class Header ( Config.h )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __CC_STATD_CONFIG_H__
#define __CC_STATD_CONFIG_H__
void StringSplit(string str, string delim, vector<string> &results, bool bUseEmpty /*= false*/);
class CDataBaseInfo
{
public:
CDataBaseInfo() {}
~CDataBaseInfo() {}
public:
int m_poolcnt;
string m_connstr;
};
class CCommonConfig
{
public:
CCommonConfig( string szFilename, string szProgramName );
virtual ~CCommonConfig();
bool LoadConf();
bool CheckValue();
void PrintValue();
inline const char * GetErrMessage() { return m_szErrMessage.c_str(); }
inline const char * GetAppLogRoot() { return m_szAppLogRoot.c_str(); }
inline int GetAppLogLevel() { return m_nLogLevel; }
protected:
string m_szConfigFile;
string m_szProgramName;
string m_szErrMessage;
// log
string m_szAppLogRoot;
int m_nLogLevel;
private:
};
class CMyConfig : public CCommonConfig
{
public:
static bool Init( string szProgramName, string szFilename );
static void Exit();
static CMyConfig* GetInstance();
private:
static CMyConfig* m_pInstance;
public:
bool LoadConf();
bool CheckValue();
inline int GetTCPListenPort() { return m_TcpListenPort; }
inline int GetWorkProcessCnt() { return m_WorkProcessCnt; }
inline int GetWorkThreadCnt() { return m_WorkThreadCnt; }
inline int GetUsedDBTypeCnt() { return m_usedDBTypeVec.size(); }
inline const char * GetUsedDBType(int index) { return m_usedDBTypeVec[index].c_str(); }
bool FindUsedDBType(string & k);
inline int GetDBInfoCnt() { return m_DBInfoMap.size(); }
inline void GetDBInfo( string key, map<string, CDataBaseInfo> & info) { info = m_DBInfoMap.find(key)->second; }
void SetFailLogPath(string & path);
inline const char * GetFailLogPath() { return m_FailLogPath.c_str(); }
void PrintValue();
protected:
CMyConfig( string szFilename, string szProgramName );
virtual ~CMyConfig();
protected:
int m_TcpListenPort;
int m_WorkProcessCnt;
int m_WorkThreadCnt;
vector<string> m_usedDBTypeVec;
map<string, map<string, CDataBaseInfo> > m_DBInfoMap;
string m_FailLogPath;
private:
};
#endif // __CC_STATD_CONFIG_H__
+225
View File
@@ -0,0 +1,225 @@
/***************************************************************************
DB Manager Class (DBManager.cpp)
-----------------------------------------
begin : 2013/06/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/06/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "DBManager.h"
#include "Configs.h"
#include "Logger.h"
static string toLowerCaseSTD(string str)
{
string ret;
ret.resize(str.size());
transform(str.begin(), str.end(), ret.begin(), ::tolower);
return ret;
}
// class CDBPools
CDBPools::CDBPools()
: m_size(0), m_dbtype(""), m_comstr(""), m_pool(NULL)
{
}
CDBPools::~CDBPools()
{
}
bool CDBPools::Create(string dbtype, int size, string comstr)
{
ostringstream msg;
try
{
m_size = size;
m_comstr = comstr;
m_dbtype = dbtype;
m_pool = new connection_pool(m_size);
if(m_pool == NULL)
{
msg << "Memory allocation failed.";
LOGACONSOLE(LERR, msg);
return false;
}
for (size_t i = 0; i != m_size; ++i)
{
session & sql = m_pool->at(i);
//sql.open(toLowerCaseSTD(m_dbtype), comstr);
// 2014.11.24 SOCI static library »ç¿ë Çϱâ À§ÇÑ ¹æ¹ý
if(m_dbtype == "POSTGRESQL" )
{
sql.open(*soci::factory_postgresql(), comstr);
}
else
{
msg << "The type is not supported.";
msg << "[" << dbtype << "]";
LOGACONSOLE(LERR, msg);
return false;
}
}
}
catch (soci_error const &e)
{
if(m_pool)
{
delete m_pool;
m_pool = NULL;
}
msg << "Failed to create the database connection pool. ";
msg << "[" << dbtype << "," << comstr <<"]";
LOGACONSOLE(LERR, msg);
msg << "Database Error message : " << e.what();
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
void CDBPools::Finalized()
{
_LOG(LDEV1, "DB Pool Stop.");
ostringstream msg;
try
{
if(m_pool)
{
delete m_pool;
m_pool = NULL;
}
}
catch (soci_error const &e)
{
msg << "Error message : " << e.what();
LOGACONSOLE(LERR, msg);
}
}
bool CDBPools::GetDB(size_t & pos, int timeout /*= DB_POO_TIMEOUT */)
{
ostringstream msg;
try
{
if(m_pool->try_lease(pos, timeout) == false)
{
msg << "Acquired DB Pool timeout.";
LOGACONSOLE(LERR, msg);
return false;
}
}
catch (soci_error const &e)
{
msg << "Error message : " << e.what();
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
void CDBPools::ReleaseDB(size_t pos)
{
ostringstream msg;
try
{
m_pool->give_back(pos);
}
catch (soci_error const &e)
{
msg << "Error message : " << e.what();
LOGACONSOLE(LERR, msg);
}
}
// class CDBManager
CDBManager::CDBManager()
: m_dbCnt(0)
{
}
CDBManager::~CDBManager()
{
}
bool CDBManager::CreatePool(string sDBtype, string sUsed, CDataBaseInfo& info)
{
++m_dbCnt;
_LOG(LDBG, "PID[%d] DB Pool type = %s, used = %s, info = %s:%d",
getpid(), sDBtype.c_str(), sUsed.c_str(),
info.m_connstr.c_str(), info.m_poolcnt);
map<string, CDBPools> m;
pair<map<string, CDBPools>::iterator,bool> ret;
pair< map<string, map<string, CDBPools > >::iterator,bool> r;
r = m_manager.insert(make_pair(sDBtype, m));
bool re = true;
ret = r.first->second.insert(make_pair(sUsed, CDBPools()));
if(ret.second == false)
{
re = false;
LOG(LERR, "Failed to create the map [%s] dupliaion.", sUsed.c_str());
}
else
{
re = ret.first->second.Create(sDBtype, info.m_poolcnt, info.m_connstr);
}
return re;
}
void CDBManager::Finalized()
{
_LOG(LDEV1, "DB Manager Finalized.");
map<string, map<string, CDBPools> >::iterator m;
m = m_manager.begin();
while(m != m_manager.end())
{
map<string, CDBPools>::iterator it = m->second.begin();
while( it != m->second.end())
{
it->second.Finalized();
it ++;
}
m->second.clear();
m ++;
}
m_manager.clear();
}
CDBPools * CDBManager::GetDBPool(string sDBtype, string sUsed)
{
CDBPools *r = NULL;
map<string, map<string, CDBPools> >::iterator find ;
find = m_manager.find(sDBtype);
if(find != m_manager.end())
{
map<string, CDBPools>::iterator f;
f = find->second.find(sUsed);
if(f != find->second.end() )
{
r = &f->second;
}
}
return r;
}
+61
View File
@@ -0,0 +1,61 @@
/***************************************************************************
DB Manager Class Header ( DBManager.h )
-----------------------------------------
begin : 2013/06/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/06/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __DB_MANAGER_H__
#define __DB_MANAGER_H__
#define DB_POO_TIMEOUT 30000 // milliseconds(30 sec)
class CDataBaseInfo;
class CDBPools
{
public:
CDBPools();
~CDBPools();
bool Create(string dbtype, int size, string comstr);
void Finalized();
bool GetDB(size_t & pos, int timeout = DB_POO_TIMEOUT );
void ReleaseDB( size_t pos);
inline session & GetSession(size_t pos) { return m_pool->at(pos); }
private:
size_t m_size;
string m_dbtype;
string m_comstr;
connection_pool * m_pool;
};
class CDBManager
{
public:
CDBManager();
~CDBManager();
bool CreatePool(string sDBtype, string sUsed, CDataBaseInfo& info);
void Finalized();
CDBPools * GetDBPool(string sDBtype, string sUsed);
protected:
private:
int m_dbCnt;
map<string, map<string, CDBPools> >m_manager;
};
#endif // __DB_MANAGER_H__
+92
View File
@@ -0,0 +1,92 @@
/***************************************************************************
Data Define Header ( DataDefine.h )
-----------------------------------------
begin : 2013/06/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/06/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __DATA_DEFINE_H__
#define __DATA_DEFINE_H__
#define XML_STR_ROOT "CCSTAT"
#define XML_SVC "SERVICE"
#define XML_SVC_RC "RC"
#define XML_SVC_USER_SEQ "USERSEQ"
#define XML_SVC_SEQ "SVCSEQ"
#define XML_SVC_NAME "SVCNAME"
#define XML_STAT "STAT"
#define XML_STAT_TIME "TIME"
#define XML_STAT_ACCESS "ACCESS"
#define XML_STAT_ACCESS_UP_SUCCESS_COUNT "UP_SUCCESS_COUNT"
#define XML_STAT_ACCESS_DOWN_SUCCESS_COUNT "DOWN_SUCCESS_COUNT"
#define XML_STAT_ACCESS_UP_AUTH_FAIL_COUNT "UP_AUTH_FAIL_COUNT"
#define XML_STAT_ACCESS_DOWN_AUTH_FAIL_COUNT "DOWN_AUTH_FAIL_COUNT"
#define XML_STAT_ACCESS_UP_ILLEGAL_REQ_COUNT "UP_ILLEGAL_REQ_COUNT"
#define XML_STAT_ACCESS_DOWN_ILLEGAL_REQ_COUNT "DOWN_ILLEGAL_REQ_COUNT"
#define XML_STAT_ACCESS_UP_TIMEOUT_COUNT "UP_TIMEOUT_COUNT"
#define XML_STAT_ACCESS_DOWN_TIMEOUT_COUNT "DOWN_TIMEOUT_COUNT"
#define XML_STAT_ACCESS_UP_DISCONNECT_COUNT "UP_DISCONNECT_COUNT"
#define XML_STAT_ACCESS_DOWN_DISCONNECT_COUNT "DOWN_DISCONNECT_COUNT"
#define XML_STAT_ACCESS_VALUE_LIST XML_STAT_ACCESS_UP_SUCCESS_COUNT","\
XML_STAT_ACCESS_DOWN_SUCCESS_COUNT","\
XML_STAT_ACCESS_UP_AUTH_FAIL_COUNT","\
XML_STAT_ACCESS_DOWN_AUTH_FAIL_COUNT","\
XML_STAT_ACCESS_UP_ILLEGAL_REQ_COUNT","\
XML_STAT_ACCESS_DOWN_ILLEGAL_REQ_COUNT","\
XML_STAT_ACCESS_UP_TIMEOUT_COUNT","\
XML_STAT_ACCESS_DOWN_TIMEOUT_COUNT","\
XML_STAT_ACCESS_UP_DISCONNECT_COUNT","\
XML_STAT_ACCESS_DOWN_DISCONNECT_COUNT
#define XML_STAT_STORAGE "STORAGE"
#define XML_STAT_STORAGE_STG_SIZE "STG_SIZE"
#define XML_STAT_STORAGE_USED_STG_SIZE "USED_STG_SIZE"
#define XML_STAT_STORAGE_VALUE_LIST XML_STAT_STORAGE_STG_SIZE","\
XML_STAT_STORAGE_USED_STG_SIZE
#define XML_STAT_NETWORK "NETWORK"
#define XML_STAT_NETWORK_UP_TRAFFIC "UP_TRAFFIC"
#define XML_STAT_NETWORK_DOWN_TRAFFIC "DOWN_TRAFFIC"
#define XML_STAT_NETWORK_UP_SIZE "UP_SIZE"
#define XML_STAT_NETWORK_DOWN_SIZE "DOWN_SIZE"
#define XML_STAT_NETWORK_UP_CONCURRENT_SESS "UP_CONCURRENT_SESS"
#define XML_STAT_NETWORK_DOWN_CONCURRENT_SESS "DOWN_CONCURRENT_SESS"
#define XML_STAT_NETWORK_VALUE_LIST XML_STAT_NETWORK_UP_TRAFFIC","\
XML_STAT_NETWORK_DOWN_TRAFFIC","\
XML_STAT_NETWORK_UP_SIZE","\
XML_STAT_NETWORK_DOWN_SIZE","\
XML_STAT_NETWORK_UP_CONCURRENT_SESS","\
XML_STAT_NETWORK_DOWN_CONCURRENT_SESS
#define XML_STAT_TRANSFER "TRANSFER"
#define XML_STAT_TRANSFER_SESSION_ID "SESSION_ID"
#define XML_STAT_TRANSFER_CONTENT_NAME "CONTENT_NAME"
#define XML_STAT_TRANSFER_TRANSFER_SIZE "TRANSFER_SIZE"
#define XML_STAT_TRANSFER_DIRECTION "DIRECTION"
#define XML_STAT_TRANSFER_START_DATE "START_DATE"
#define XML_STAT_TRANSFER_END_DATE "END_DATE"
#define XML_STAT_TRANSFER_REPONSE_CODE "REPONSE_CODE"
#define XML_STAT_TRANSFER_VALUE_LIST XML_STAT_TRANSFER_SESSION_ID","\
XML_STAT_TRANSFER_CONTENT_NAME","\
XML_STAT_TRANSFER_TRANSFER_SIZE","\
XML_STAT_TRANSFER_DIRECTION","\
XML_STAT_TRANSFER_START_DATE","\
XML_STAT_TRANSFER_END_DATE","\
XML_STAT_TRANSFER_REPONSE_CODE
#define XML_FAIL "FAIL"
#define XML_FAIL_DATABASE "DATABASE"
#define XML_FAIL_TYPE "TYPE"
#define USED_TYPE_ORACLE "ORACLE"
#define USED_TYPE_POSTGRESQL "POSTGRESQL"
#define USED_KIND_STAT "STAT"
#define USED_KIND_LOG "LOG"
#define USED_KIND_INTEGRATE "INTEGRATE"
#endif // __DATA_DEFINE_H__
+290
View File
@@ -0,0 +1,290 @@
/***************************************************************************
Insert Class ( Insert.cpp )
-----------------------------------------
begin : 2013/07/09
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/09 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Insert.h"
#include "DataDefine.h"
#include "Configs.h"
#include "Logger.h"
#define TIME_STRING_LAN 30
//
void CInsert::timeToString(time_t stamp, char *buf)
{
struct tm *_tm;
_tm = localtime(&stamp);
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", (1900 + _tm->tm_year),
(_tm->tm_mon + 1), _tm->tm_mday, _tm->tm_hour,
_tm->tm_min, _tm->tm_sec);
}
bool CInsert::run(string strsql, session & sql)
{
bool r = true;
ostringstream msg;
try
{
sql << strsql;
if (sql.get_backend_name() == "oracle")
{
sql.commit();
}
}
catch (soci_error const &e)
{
r = false;
msg << "Error message : " << e.what();
msg << "SQL : " << strsql;
LOGACONSOLE(LERR, msg);
}
if(r == false )
{
bool f = false;
try
{
sql.rollback();
}
catch (soci_error const &e)
{
f = true;
msg << "Error(rollback) message : " << e.what();
LOGACONSOLE(LERR, msg);
}
if(f)
{
try
{
sql.reconnect();
msg << "Success database reconnection.";
LOGACONSOLE(LWAR, msg);
}
catch (soci_error const &e)
{
msg << "Error(reconnect) message : " << e.what();
LOGACONSOLE(LERR, msg);
}
}
}
return r;
}
// Postgresql
bool CInsertPostgresqlAccess::Insert(map <string, string > &svc, map <string, string > &val, session & sql)
{
LOG(LDEV1, "Insert : %s-%s", USED_TYPE_POSTGRESQL, XML_STAT_ACCESS );
ostringstream sqlstr;
char szTimeStr[TIME_STRING_LAN] = {0};
time_t t = atoi(val[XML_STAT_TIME].c_str()) * 300 ;
timeToString(t, szTimeStr);
/* side : cs_stat_access */
sqlstr << "INSERT INTO cs_stat.cs_stat_access "
<< "("
<< "reg_date, "
<< "user_seq, svc_seq, rc_id, "
<< "up_success_count, down_success_count, "
<< "up_auth_fail_count, down_auth_fail_count, "
<< "up_illegal_req_count, down_illegal_req_count, "
<< "up_timeout_count, down_timeout_count, "
<< "up_disconnect_count, down_disconnect_count"
<< ") "
<< "VALUES "
<< "("
<< "'" << szTimeStr << "', "
<< svc[XML_SVC_USER_SEQ] << ", "
<< svc[XML_SVC_SEQ] << ", "
<< "'" << svc[XML_SVC_RC] << "',"
<< val[XML_STAT_ACCESS_UP_SUCCESS_COUNT] << ", "
<< val[XML_STAT_ACCESS_DOWN_SUCCESS_COUNT] << ", "
<< val[XML_STAT_ACCESS_UP_AUTH_FAIL_COUNT] << ", "
<< val[XML_STAT_ACCESS_DOWN_AUTH_FAIL_COUNT] << ", "
<< val[XML_STAT_ACCESS_UP_ILLEGAL_REQ_COUNT] << ", "
<< val[XML_STAT_ACCESS_DOWN_ILLEGAL_REQ_COUNT] << ", "
<< val[XML_STAT_ACCESS_UP_TIMEOUT_COUNT] << ", "
<< val[XML_STAT_ACCESS_DOWN_TIMEOUT_COUNT] << ", "
<< val[XML_STAT_ACCESS_UP_DISCONNECT_COUNT] << ", "
<< val[XML_STAT_ACCESS_DOWN_DISCONNECT_COUNT] << ""
<< ")";
return run(sqlstr.str(), sql);
}
bool CInsertPostgresqlStorage::Insert(map <string, string > &svc, map <string, string > &val, session & sql)
{
LOG(LDEV1, "Insert : %s-%s", USED_TYPE_POSTGRESQL, XML_STAT_STORAGE );
ostringstream sqlstr;
char szTimeStr[TIME_STRING_LAN] = {0};
time_t t = atoi(val[XML_STAT_TIME].c_str()) * 300 ;
timeToString(t, szTimeStr);
/* side : cs_stat_storage */
sqlstr << "INSERT INTO cs_stat.cs_stat_storage "
<< "("
<< "reg_date, "
<< "user_seq, svc_seq, rc_id, "
<< "stg_size, used_stg_size"
<< ") "
<< "VALUES "
<< "("
<< "'" << szTimeStr << "', "
<< svc[XML_SVC_USER_SEQ] << ", "
<< svc[XML_SVC_SEQ] << ", "
<< "'" << svc[XML_SVC_RC] << "',"
<< val[XML_STAT_STORAGE_STG_SIZE] << ", "
<< val[XML_STAT_STORAGE_USED_STG_SIZE] << ""
<<")";
return run(sqlstr.str(), sql);
}
bool CInsertPostgresqlNetwork::Insert(map <string, string > &svc, map <string, string > &val, session & sql)
{
LOG(LDEV1, "Insert : %s-%s", USED_TYPE_POSTGRESQL, XML_STAT_NETWORK );
ostringstream sqlstr;
char szTimeStr[TIME_STRING_LAN] = {0};
time_t t = atoi(val[XML_STAT_TIME].c_str()) * 300 ;
timeToString(t, szTimeStr);
/* side : cs_stat_network */
sqlstr << "INSERT INTO cs_stat.cs_stat_network "
<< "("
<< "reg_date, "
<< "user_seq, svc_seq, rc_id, "
<< "up_traffic, down_traffic, "
<< "up_size, down_size, "
<< "up_concurrent_sess, down_concurrent_sess"
<< ") "
<< "VALUES "
<< "("
<< "'" << szTimeStr << "', "
<< svc[XML_SVC_USER_SEQ] << ", "
<< svc[XML_SVC_SEQ] << ", "
<< "'" << svc[XML_SVC_RC] << "',"
<< val[XML_STAT_NETWORK_UP_TRAFFIC] << ", "
<< val[XML_STAT_NETWORK_DOWN_TRAFFIC] << ", "
<< val[XML_STAT_NETWORK_UP_SIZE] << ", "
<< val[XML_STAT_NETWORK_DOWN_SIZE] << ", "
<< val[XML_STAT_NETWORK_UP_CONCURRENT_SESS] << ", "
<< val[XML_STAT_NETWORK_DOWN_CONCURRENT_SESS] << ""
<<")";
return run(sqlstr.str(), sql);
}
bool CInsertPostgresqlTransfer::Insert(map <string, string > &svc, map <string, string > &val, session & sql)
{
LOG(LDEV1, "Insert : %s-%s", USED_TYPE_POSTGRESQL, XML_STAT_TRANSFER );
ostringstream sqlstr;
char szBeginTimeStr[TIME_STRING_LAN] = {0};
char szEndTimeStr[TIME_STRING_LAN] = {0};
time_t t1 = atoi(val[XML_STAT_TRANSFER_START_DATE].c_str()) ;
time_t t2 = atoi(val[XML_STAT_TRANSFER_END_DATE].c_str()) ;
timeToString(t1, szBeginTimeStr);
timeToString(t1, szEndTimeStr);
/* side : cs_stat_transfer */
sqlstr << "INSERT INTO cs_stat.cs_stat_transfer "
<< "("
<< "reg_date, "
<< "user_seq, svc_seq, rc_id, "
<< "session_id, "
<< "content_name, transfer_size, direction, "
<< "start_date, end_date, response_code"
<< ") "
<< "VALUES "
<< "("
<< "NOW(), "
<< svc[XML_SVC_USER_SEQ] << ", "
<< svc[XML_SVC_SEQ] << ", "
<< "'" << svc[XML_SVC_RC] << "',"
<< "'" << val[XML_STAT_TRANSFER_SESSION_ID] << "', "
<< "'" << val[XML_STAT_TRANSFER_CONTENT_NAME] << "', "
<< val[XML_STAT_TRANSFER_TRANSFER_SIZE] << ", "
<< val[XML_STAT_TRANSFER_DIRECTION] << ", "
<< "'" << szBeginTimeStr << "', "
<< "'" << szEndTimeStr << "', "
<< val[XML_STAT_TRANSFER_REPONSE_CODE] << ""
<< ")";
return run(sqlstr.str(), sql);
}
// Abstract Factory returning a Insert
CInsert* CInsertFactory::Create(string dbtype, string dtype)
{
CInsert *r = NULL;
if(dbtype.find(USED_TYPE_ORACLE) != string::npos)
{
// 2014.11.20 : 오라클을 사용하는 곳 없으므로 삭제 처리
r = NULL;
}
else if (dbtype.find(USED_TYPE_POSTGRESQL) != string::npos)
{
if( dtype.find(XML_STAT_ACCESS) != string::npos )
{
m_dbtype = USED_TYPE_POSTGRESQL;
m_usedtype = USED_KIND_STAT;
r = new CInsertPostgresqlAccess;
}
else if ( dtype.find(XML_STAT_STORAGE) != string::npos )
{
m_dbtype = USED_TYPE_POSTGRESQL;
m_usedtype = USED_KIND_STAT;
r = new CInsertPostgresqlStorage;
}
else if ( dtype.find(XML_STAT_NETWORK) != string::npos )
{
m_dbtype = USED_TYPE_POSTGRESQL;
m_usedtype = USED_KIND_STAT;
r = new CInsertPostgresqlNetwork;
}
else if ( dtype.find(XML_STAT_TRANSFER) != string::npos )
{
m_dbtype = USED_TYPE_POSTGRESQL;
m_usedtype = USED_KIND_STAT;
r = new CInsertPostgresqlTransfer;
}
else
{
r = NULL;
}
}
else
{
r = NULL;
}
LOG(LDEV1, "Insert type.[%s::%s::%s]", m_dbtype.c_str(), m_usedtype.c_str(), dtype.c_str());
if(r == NULL)
{
LOG(LERR, "Unknown database type.[%s-%s]", dbtype.c_str(), dtype.c_str());
}
return r;
}
+82
View File
@@ -0,0 +1,82 @@
/***************************************************************************
Insert Class Header ( InsertData.h )
-----------------------------------------
begin : 2013/07/09
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/09 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __INSERT_H__
#define __INSERT_H__
class CInsert
{
public:
CInsert() {};
virtual ~CInsert() {};
virtual bool Insert(map <string, string > &svc, map <string, string > &val, session & sql) = 0;
protected:
bool run(string strsql, session & sql);
void timeToString(time_t stamp, char *buf);
};
// Postgresql
class CInsertPostgresqlAccess : public CInsert
{
public:
CInsertPostgresqlAccess() {};
virtual ~CInsertPostgresqlAccess() {};
virtual bool Insert(map <string, string > &svc, map <string, string > &val, session & sql);
};
class CInsertPostgresqlStorage : public CInsert
{
public:
CInsertPostgresqlStorage() {};
virtual ~CInsertPostgresqlStorage() {};
virtual bool Insert(map <string, string > &svc, map <string, string > &val, session & sql);
};
class CInsertPostgresqlNetwork : public CInsert
{
public:
CInsertPostgresqlNetwork() {};
virtual ~CInsertPostgresqlNetwork() {};
virtual bool Insert(map <string, string > &svc, map <string, string > &val, session & sql);
};
class CInsertPostgresqlTransfer : public CInsert
{
public:
CInsertPostgresqlTransfer() {};
virtual ~CInsertPostgresqlTransfer() {};
virtual bool Insert(map <string, string > &svc, map <string, string > &val, session & sql);
};
// Abstract Factory returning a Insert
class CInsertFactory
{
public:
CInsert* Create(string dbtype, string dtype);
inline string GetDBType() { return m_dbtype; }
inline string GetUsedType() { return m_usedtype; }
private:
string m_dbtype;
string m_usedtype;
};
#endif // __INSERT_H__
+437
View File
@@ -0,0 +1,437 @@
/***************************************************************************
Insert Data Class ( InsertData.cpp )
-----------------------------------------
begin : 2013/07/03
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/03 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "InsertData.h"
#include "Insert.h"
#include "DBManager.h"
#include "Configs.h"
#include "Logger.h"
CInsertData::CInsertData()
{
}
CInsertData::CInsertData(string &rc, string &userseq, string &svcseq, string &svcname)
{
m_svc[XML_SVC_RC] = rc;
m_svc[XML_SVC_USER_SEQ] = userseq;
m_svc[XML_SVC_SEQ] = svcseq;
m_svc[XML_SVC_NAME] = svcname;
}
CInsertData::~CInsertData()
{
Clear();
}
void CInsertData::Clear()
{
ClearJobLog();
ClearKey();
m_svc.clear();
m_stat.clear();
m_failtype.clear();
m_insertfail.clear();
}
void CInsertData::MakeStatKey(string stattype, string val)
{
ClearKey();
m_key.append( stattype );
m_key.append( "-" );
m_key.append( val );
}
void CInsertData::MakeInsertFailKey(string failtype)
{
ClearKey();
m_key.append(failtype);
}
void CInsertData::SetServiceInfo(string &rc, string &userseq, string &svcseq, string &svcname)
{
m_svc[XML_SVC_RC] = rc;
m_svc[XML_SVC_USER_SEQ] = userseq;
m_svc[XML_SVC_SEQ] = svcseq;
m_svc[XML_SVC_NAME] = svcname;
}
bool CInsertData::SetStat(string valuetype, string val)
{
if(m_key.empty())
{
LOG(LERR, "InsertData Key empty.");
return false;
}
map<string, string> v;
v.insert(make_pair(valuetype, val));
std::pair<map<string, map <string, string > >::iterator, bool> ret;
ret = m_stat.insert(make_pair(m_key, v));
if (ret.second==false)
{
std::pair<map <string, string >::iterator, bool> r;
r = ret.first->second.insert(make_pair(valuetype, val));
if (r.second==false)
{
LOG(LERR, "InsertData element '%s' already existed.", valuetype.c_str());
return false;
}
}
return true;
}
bool CInsertData::SetInsertFail(string statkey, string valuetype, string val)
{
if(m_key.empty())
{
LOG(LERR, "InsertData(Fail) Key empty.");
return false;
}
map<string, string> v;
v.insert(make_pair(valuetype, val));
map<string, map<string, string > > v2;
v2.insert(make_pair(statkey, v));
std::pair<map< string, map<string, map <string, string > > >::iterator, bool> ret;
ret = m_insertfail.insert(make_pair(m_key, v2));
if (ret.second==false)
{
std::pair<map<string, map <string, string > >::iterator, bool> ret2;
ret2 = ret.first->second.insert(make_pair(statkey, v));
if (ret2.second==false)
{
std::pair<map <string, string >::iterator, bool> ret3;
ret3 = ret2.first->second.insert(make_pair(valuetype,val));
if(ret3.second == false)
{
LOG(LERR, "InsertData(Fail) element '%s' already existed.", valuetype.c_str());
return false;
}
}
}
// save fail
m_joblog[1] += (statkey + "|");
return true;
}
bool CInsertData::SetInsertFail(string statkey, map <string, string > &val)
{
if(m_key.empty())
{
LOG(LERR, "InsertData(Fail) Key empty.");
return false;
}
map<string, map <string, string > > v;
v.insert(make_pair(statkey, val));
std::pair<map< string, map<string, map <string, string > > >::iterator, bool> ret;
ret = m_insertfail.insert(make_pair(m_key, v));
if (ret.second==false)
{
std::pair<map<string, map <string, string > >::iterator, bool> ret2;
ret2 = ret.first->second.insert(make_pair(statkey, val));
if (ret2.second==false)
{
LOG(LERR, "InsertData(Fail) element '%s' already existed.", statkey.c_str());
return false;
}
}
// save fail
m_joblog[1] += (statkey + "|");
return true;
}
bool CInsertData::FindFailType(string stype)
{
// find
vector<string>::iterator i = find(m_failtype.begin(), m_failtype.end(), stype);
if (i!= m_failtype.end())
{
// found it
return true;
}
else
{
// doesn't exist
return false;
}
return true;
}
bool CInsertData::ExecuteInsert(string stype, CDBManager* dbmanager)
{
bool r = true;
map<string, map <string, string > >::iterator it;
for (it=m_stat.begin(); it!= m_stat.end(); ++it)
{
CInsert *i = NULL;
CInsertFactory f;
i = f.Create(stype, it->first);
if( i )
{
CDBPools * pool = dbmanager->GetDBPool(f.GetDBType(), USED_KIND_INTEGRATE);
if(!pool)
{
pool = dbmanager->GetDBPool(f.GetDBType(), f.GetUsedType());
if(!pool)
{
r = false;
SetInsertFail(it->first, it->second);
LOG(LERR, "There isn't type of database that you want to use.");
continue;
}
}
size_t pos = 0;
if(pool->GetDB(pos))
{
LOG(LDEV1, "Database POOL POS [%zu].", pos);
try
{
if(i->Insert(m_svc, it->second, pool->GetSession(pos)) == false)
{
r = false;
SetInsertFail(it->first, it->second);
}
else
{
// save success
m_joblog[0] += (it->first + "|");
LOG(LDEV2, "Insert Success :%s => %s, %s "
, f.GetDBType().c_str(), m_svc[XML_SVC_SEQ].c_str()
, it->first.c_str());
}
pool->ReleaseDB(pos);
}
catch (soci_error const &e)
{
r = false;
LOG(LERR, "Database POOL Error message :%s", e.what());
}
}
else
{
// fail
r = false;
SetInsertFail(it->first, it->second);
LOG(LERR, "Database POOL acquisition failure.");
}
delete i;
}
else
{
r = false;
SetInsertFail(it->first, it->second);
}
}
return r;
}
bool CInsertData::MakeXMLNode(Element* root)
{
ostringstream msg;
try
{
if ( m_insertfail.empty() )
return false;
map<string, map<string, map <string, string > > >::iterator it;
for (it=m_insertfail.begin(); it!= m_insertfail.end(); ++it)
{
// Set Service
Element* service = root->add_child(XML_SVC);
/// Set attributes : RC, USERSEQ, SVCSEQ, SVCNAME
service->set_attribute(XML_SVC_RC, m_svc[XML_SVC_RC]);
service->set_attribute(XML_SVC_USER_SEQ, m_svc[XML_SVC_USER_SEQ]);
service->set_attribute(XML_SVC_SEQ, m_svc[XML_SVC_SEQ]);
service->set_attribute(XML_SVC_NAME, m_svc[XML_SVC_NAME]);
/// Set Stat
Element* stats = service->add_child(XML_STAT);
//// ACCESS, STORAGE, NETWORK, TRANSFER
map<string, map <string, string > >::iterator it2;
for(it2=it->second.begin();it2!= it->second.end(); ++it2 )
{
vector<string> stattype;
StringSplit(it2->first, "-", stattype, true);
if( stattype.size() != 2 )
{
LOG(LWAR, "Stat Type is invalid.[%s]", it2->first.c_str())
continue;
}
Element* statdata = stats->add_child(stattype[0]);
map <string, string >::iterator it3;
for(it3=it2->second.begin();it3!= it2->second.end(); ++it3 )
{
std::size_t found = it3->first.find(XML_STAT_TIME);
if( found != string::npos && found == 0)
{
statdata->set_attribute(XML_STAT_TIME, stattype[1]);
}
else
{
Element* val = statdata->add_child(it3->first);
val->set_child_text(it3->second);
}
}
}
/// Set Fail
Element* faildb = service->add_child(XML_FAIL);
//// Set Fail Database
Element* dbtype = faildb->add_child(XML_FAIL_DATABASE);
dbtype->set_attribute(XML_FAIL_TYPE, it->first);
}
}
catch(const std::exception& ex)
{
msg << "Exception caught: " << ex.what();
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
void CInsertData::PrintServiceInfo()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
ostringstream msg;
msg << "Service Info: " << GetRC() << "," << GetUserSEQ()
<< "," << GetSvcSEQ() << "," << GetSvcName();
LOGACONSOLE(LDEV1, msg);
}
void CInsertData::PrintStat()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
ostringstream msg;
map<string, map <string, string > >::iterator it;
map <string, string >::iterator it2;
msg << "Stat Data [" << GetSvcSEQ() << "] => " << m_stat.size();
LOGACONSOLE(LDEV1, msg);
for (it=m_stat.begin(); it!= m_stat.end(); ++it)
{
msg << it->first << ":";
for(it2=it->second.begin();it2!= it->second.end(); ++it2 )
{
msg << it2->first << " => " << it2->second << ",";
}
LOGACONSOLE(LDEV1, msg);
}
msg << "Stat Data <= [" << GetSvcSEQ() << "]";
LOGACONSOLE(LDEV1, msg);
}
void CInsertData::PrintFailType()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
ostringstream msg;
msg << "Fail Data [" << GetSvcSEQ() << "] => " << m_failtype.size();
LOGACONSOLE(LDEV1, msg);
msg << "Fail Database Type :";
for (unsigned int i = 0; i < m_failtype.size(); ++i)
{
msg << " " << m_failtype[i];
}
LOGACONSOLE(LDEV1, msg);
msg << "Fail Data <= [" << GetSvcSEQ() << "]";
LOGACONSOLE(LDEV1, msg);
}
void CInsertData::PrintInsertFail()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
ostringstream msg;
map<string, map<string, map <string, string > > >::iterator it;
map<string, map <string, string > >::iterator it2;
map <string, string >::iterator it3;
msg << "Insert Fail Data [" << GetSvcSEQ() << "] => " << m_insertfail.size();
LOGACONSOLE(LDEV1, msg);
for (it=m_insertfail.begin(); it!= m_insertfail.end(); ++it)
{
msg << it->first << ":";
for(it2=it->second.begin();it2!= it->second.end(); ++it2 )
{
msg << it2->first << " : ";
for(it3=it2->second.begin();it3!= it2->second.end(); ++it3 )
{
msg << it3->first << " => " << it3->second << ",";
}
}
LOGACONSOLE(LDEV1, msg);
}
msg << "Insert Fail Data <= [" << GetSvcSEQ() << "]";
LOGACONSOLE(LDEV1, msg);
}
void CInsertData::PrintStatAll()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
PrintServiceInfo();
PrintStat();
PrintFailType();
}
void CInsertData::PrintInsertFailAll()
{
if( CLogger::GetInstance()->GetLogLevel() <= LDBG )
return;
PrintServiceInfo();
PrintInsertFail();
}
+78
View File
@@ -0,0 +1,78 @@
/***************************************************************************
Insert Data Class Header ( InsertData.h )
-----------------------------------------
begin : 2013/07/03
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/03 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __INSERT_DATA_H__
#define __INSERT_DATA_H__
#include "DataDefine.h"
class CDBManager;
class CInsertData
{
public:
CInsertData();
CInsertData(string &rc, string &userseq, string &svcseq, string &svcname);
virtual ~CInsertData();
void MakeStatKey(string stattype, string val);
void MakeInsertFailKey(string failtype);
void SetServiceInfo(string &rc, string &userseq, string &svcseq, string &svcname);
bool SetStat(string valuetype, string val);
inline void SetFailType(string val) { m_failtype.push_back(val); }
bool SetInsertFail(string statkey, string valuetype, string val);
bool SetInsertFail(string statkey, map <string, string > &val);
bool FindFailType(string stype);
bool ExecuteInsert(string stype, CDBManager* dbmanager);
bool MakeXMLNode(Element* root);
inline const char* GetRC() { return m_svc[XML_SVC_RC].c_str(); }
inline const char* GetUserSEQ() { return m_svc[XML_SVC_USER_SEQ].c_str(); }
inline const char* GetSvcSEQ() { return m_svc[XML_SVC_SEQ].c_str(); }
inline const char* GetSvcName() { return m_svc[XML_SVC_NAME].c_str(); }
inline const char* GetFailType(int i) { return m_failtype[i].c_str(); }
inline const char* GetSuccess() { return m_joblog[0].c_str(); }
inline const char* GetFail() { return m_joblog[1].c_str(); }
inline int FailTypeSize() { return m_failtype.size(); }
inline void ClearJobLog() { m_joblog[0].clear(); m_joblog[1].clear(); }
inline void ClearKey() { m_key.clear(); }
void Clear();
void PrintServiceInfo();
void PrintStat();
void PrintFailType();
void PrintStatAll();
void PrintInsertFail();
void PrintInsertFailAll();
private:
string m_key;
map <string, string > m_svc;
map<string, map <string, string > > m_stat;
vector<string> m_failtype;
map<string, map<string, map <string, string > > > m_insertfail;
string m_joblog[2];
};
#endif // __INSERT_DATA_H__
+105
View File
@@ -0,0 +1,105 @@
#****************************************************************************
# Makefile for cc_statd ( CC Stat Daemon )
# -----------------------------------------
#
# begin : 2013/05/28
# copyright : (C) 2013 Solbox Inc.
# author : Development 1 Team
# - 2013/05/28 - 1st dadamin
# email : dev1@solbox.com
# version : 3.2.0
#
# CopyRight(C) 2005 Solbox Inc. All Rights reserved.
# Redistribution and use in source and binary forms, with or with out
# modification, are not permitted in outside of Solbox Inc.
#*****************************************************************************
# Program info
PROG_NAME = cc_statd
REVISION = 1142
BUILD_DATE = `date +%Y%m%d%H%M%S`
PROG_VERSION = 3.4.0.$(REVISION)-$(BUILD_DATE)
CONFIG_NAME = gts.conf
SOCI_HOME = /user/SOCI
INSTALL_HOME = /user/service
INSTALL_BIN = $(INSTALL_HOME)/bin
INSTALL_CONFIG = $(INSTALL_HOME)/etc
INSTALL_LOG_HOME = $(INSTALL_HOME)/logs
DEFAULT_CONFIG_FILE = $(INSTALL_CONFIG)/$(CONFIG_NAME)
#XML EVIRONMENT VARIABLE
XML++_INCLUDES = `pkg-config libxml++-2.6 --cflags`
XML++_LIBS = `pkg-config libxml++-2.6 --libs`
#SOCI EVIRONMENT VARIABLE
SOCI_LIBS = $(SOCI_HOME)/lib64/libsoci_core.a $(SOCI_HOME)/lib64/libsoci_postgresql.a /user/db/pgsql/lib/libpq.a
## core
SOCI_INCLUDE = $(SOCI_HOME)/include/soci
## PostgreSQL
POSTGRESQL_INCLUDE = /user/db/pgsql/include
# Compiler info
CC = /usr/bin/g++
CFLAGS = -Wall -O3 -g -Wimplicit -Wreturn-type -Wunused -Wuninitialized\
-Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual\
-minline-all-stringops -fstack-protector-all\
-D_THREAD_SAFE -D_REENTRANT -D_PTHREADS -Wno-unused -Wno-non-virtual-dtor
LFLAGS = --fast-math -march=native
# DEBUG or RELEASE Mode select
ifeq ($(DEBUG), yes)
PROG_VERSION = 3.4.0.$(REVISION)D-$(BUILD_DATE)
CFLAGS = -Wall -O0 -g -Wimplicit -Wreturn-type -Wunused\
-Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual\
-minline-all-stringops -fstack-protector-all\
-D_THREAD_SAFE -D_REENTRANT -D_PTHREADS -Wno-unused -Wno-non-virtual-dtor\
DFLAGS = $(TEST) -D_DEBUG -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\"\
-DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
else
DFLAGS = $(TEST) -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\"\
-DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
endif
# Application Enviroment
APP = $(PROG_NAME)
DIR_LIB = -L../lib -L$(INSTALL_LIBRARY)
DIR_INCLUDE = -I./. -I../lib $(XML++_INCLUDES) -I$(SOCI_INCLUDE) -I$(POSTGRESQL_INCLUDE)
LIBS = -lpthread ../lib/libInterCommon.a $(XML++_LIBS) $(SOCI_LIBS)
OBJ = Insert.o InsertData.o Work.o DBManager.o WorkPool.o\
Service.o Worker.o Signals.o Configs.o ArgParser.o main.o
############################
all:$(APP)
sync
%.o: %.cpp
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
$(PROG_NAME): $(OBJ)
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
clean:
-rm -f *.o *.core core.* .out *.log
-rm -f $(APP)
-rm -f $(DUMP_PATH)/core.*
sync
install : $(APP)
-mkdir -p $(INSTALL_HOME)
-mkdir -p $(INSTALL_BIN)
-mkdir -p $(INSTALL_CONFIG)
-mkdir -p $(INSTALL_LOG_HOME)
-mkdir -p $(DUMP_PATH)
-cp -f $(APP) $(INSTALL_BIN)/$(APP)
-cp -i ../conf/$(CONFIG_NAME) $(INSTALL_CONF)/$(CONFIG_NAME)
sync
# End of Makefile
+464
View File
@@ -0,0 +1,464 @@
/***************************************************************************
Service Class (Service.cpp)
-----------------------------------------
begin : 2013/05/30
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/30 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Service.h"
#include "Configs.h"
#include "Logger.h"
#define FAIL_LOG_PREFIX PROG_NAME"_"
#define FAIL_LOG_TAIL ".xml"
#define FAIL_LOG_WAIT_TIME 60 // sec
#define DEFAULT_ACCEPT_WAIT_COUNT 30
#define ACCEPT_TIMEOUT 60
// class CService
bool CService::Create()
{
// create work thread pool
if(m_WokrPool.CreatePool(CMyConfig::GetInstance()->GetWorkThreadCnt(), &m_DBManager) == false)
return false;
// create DB connection pool
int n = CMyConfig::GetInstance()->GetUsedDBTypeCnt();
for(int i = 0; i < n; ++i)
{
string sDBType = CMyConfig::GetInstance()->GetUsedDBType(i);
map<string, CDataBaseInfo> infos;
CMyConfig::GetInstance()->GetDBInfo(sDBType, infos);
for( map<string, CDataBaseInfo>::iterator iter2 = infos.begin(); iter2 != infos.end(); ++iter2)
{
if( m_DBManager.CreatePool(sDBType, iter2->first, iter2->second) == false)
return false;
}
}
return true;
}
bool CService::Start()
{
return true;
}
bool CService::Stop()
{
if(m_done) return true;
m_done = true;
m_WokrPool.Finalized();
m_DBManager.Finalized();
return true;
}
// class CFailLogMon
CFailLogMon::CFailLogMon()
{
}
CFailLogMon::~CFailLogMon()
{
}
bool CFailLogMon::Create()
{
if(CService::Create() == false)
return false;
m_fiallogpath = CMyConfig::GetInstance()->GetFailLogPath();
return true;
}
bool CFailLogMon::FindLog()
{
ostringstream msg;
while(!m_done)
{
msg << "Fail Log Working...";
LOGACONSOLE(LDEV1, msg);
// 특정 디렉토리 하위에 위치한 로그 탐색
DIR *dp;
struct dirent *dirp;
struct stat sb;
string sfull;
if((dp = opendir(m_fiallogpath.c_str())) != NULL)
{
bool skip = true;
while ((dirp = readdir(dp)) != NULL)
{
skip = true;
sfull = m_fiallogpath + "/" + dirp->d_name;
stat(sfull.c_str(), &sb);
if (S_ISREG(sb.st_mode))
{
// 로그 파일명 규칙 : cc_statd_YYYYMMDDHHmmSS_RandomKey.xml
if(sfull.find(FAIL_LOG_PREFIX) != string::npos &&
sfull.find(FAIL_LOG_TAIL) != string::npos)
{
skip = false;
msg << "Working File " << sfull;
LOGACONSOLE(LDBG, msg);
// work
CWorkThread *work = m_WokrPool.GetWork();
if(work)
{
work->RunWork(sfull);
}
else
{
msg << "Failed Work pool allocation. [FILE : " << sfull << "]";
LOGACONSOLE(LERR, msg);
}
}
}
if(skip)
{
if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, ".."))
{
msg << "SIKP : Fail Log worker [Path : " << sfull << "]";
LOGACONSOLE(LWAR, msg);
}
}
}
closedir(dp);
}
else
{
msg << "Error(" << errno << ") opening " << m_fiallogpath;
LOGACONSOLE(LERR, msg);
}
// sleep
sleep(FAIL_LOG_WAIT_TIME);
}
return true;
}
bool CFailLogMon::Start()
{
ostringstream msg;
msg << "Fail Log Mon START.";
LOGACONSOLE(LDEV1, msg);
FindLog();
msg << "Fail Log Mon END.";
LOGACONSOLE(LDEV1, msg);
return true;
}
bool CFailLogMon::Stop()
{
CService::Stop();
return true;
}
// class CTCPService
int CTCPService::m_port = 0;
int CTCPService::m_listenSocket = -1;
bool CTCPService::m_ipv6 = false;
void CTCPService::SetPort(int port)
{
m_port = port;
}
bool CTCPService::MakeListenSocket()
{
ostringstream msg;
if(m_listenSocket > 0)
return true;
#ifdef AF_INET6
m_listenSocket = ::socket( AF_INET6, SOCK_STREAM, 0 );
if(m_listenSocket > 0)
{
msg << "Enable IPv6 Socket.";
LOGACONSOLE(LINF, msg);
m_ipv6 = true;
}
#endif // AF_INET6
if(m_ipv6 == false)
m_listenSocket = ::socket( AF_INET, SOCK_STREAM, 0 );
if( m_listenSocket == -1 )
{
msg << "Listen socket create failed.[" << errno << "]["
<< strerror(errno) << "] [Port : " << m_port << "]";
LOGACONSOLE(LERR, msg);
return false;
}
int result = 0;
// Socket Port Reuse Option Set
int opt = 1;
result = ::setsockopt( m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );
if( result != 0 )
{
msg << "Listen socket option[SO_REUSEADDR] set failed. [" << errno
<< "][" << strerror(errno) << "][Port : " << m_port << "]";
LOGACONSOLE(LERR, msg);
return false;
}
// Keep Alive Option set
opt = 1;
result = ::setsockopt( m_listenSocket, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt) );
if( result != 0 )
{
msg << "Listen socket option[SO_KEEPALIVE] set failed. [" << errno
<< "][" << strerror(errno) << "]";
LOGACONSOLE(LERR, msg);
return false;
}
// Socket Bind
#ifdef AF_INET6
if(m_ipv6)
{
struct sockaddr_in6 listenSockAddrv6;
socklen_t listenSockLen = 0;
memset(&listenSockAddrv6, 0x00, sizeof(listenSockAddrv6));
listenSockAddrv6.sin6_family = AF_INET;
listenSockAddrv6.sin6_flowinfo = 0;
listenSockAddrv6.sin6_port = htons( m_port );
listenSockAddrv6.sin6_addr = in6addr_any;
listenSockLen = sizeof(listenSockAddrv6);
result = ::bind( m_listenSocket, (struct sockaddr *)&listenSockAddrv6, listenSockLen);
}
else
#endif //AF_INET6
{
struct sockaddr_in listenSockAddr;
socklen_t listenSockLen = 0;
bzero(&listenSockAddr,sizeof(listenSockAddr));
listenSockAddr.sin_family = AF_INET;
listenSockAddr.sin_port = htons( m_port );
listenSockAddr.sin_addr.s_addr = htonl( INADDR_ANY );
listenSockLen = sizeof(listenSockAddr);
// Socket Bind
result = ::bind( m_listenSocket, (struct sockaddr *)&listenSockAddr, listenSockLen);
}
if( result != 0 )
{
msg << "Listen socket bind failed. [" << errno << "][" << strerror(errno)
<< "][Port : " << m_port << "]";
LOGACONSOLE(LERR, msg);
return false;
}
// Socket Listen
result = ::listen( m_listenSocket, DEFAULT_ACCEPT_WAIT_COUNT );
if( result != 0 )
{
msg << "Listen socket listen failed. [" << errno << "][" << strerror(errno)
<< "][Port : " << m_port << "]";
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
CTCPService::CTCPService()
{
}
CTCPService::~CTCPService()
{
}
bool CTCPService::Create()
{
if(CService::Create() == false)
return false;
return true;
}
bool CTCPService::Accpet()
{
ostringstream msg;
// 접속 요청을 변수 생성 및 초기화.
int nClientfd;
socklen_t clientSockLen;
#ifdef AF_INET6
struct sockaddr_in6 clientSockAddrv6;
#endif //AF_INET6
struct sockaddr_in clientSockAddr;
if(m_ipv6)
clientSockLen = sizeof(clientSockAddrv6);
else
clientSockLen = sizeof(clientSockAddr);
while(!m_done)
{
pid_t pid = getpid();
#ifdef AF_INET6
if(m_ipv6)
{
msg << "Client(v6) Waiting... [Port:" << m_port << ",PID:" << pid << "]";
LOGACONSOLE(LDEV1, msg);
nClientfd = ::accept( CTCPService::m_listenSocket, (struct sockaddr *) &clientSockAddrv6, &clientSockLen );
}
else
#endif //AF_INET6
{
msg << "Client Waiting... [Port:" << m_port << ",PID:" << pid << "]";
LOGACONSOLE(LDEV1, msg);
nClientfd = ::accept( CTCPService::m_listenSocket, (struct sockaddr *) &clientSockAddr, &clientSockLen );
}
if( nClientfd == -1 )
{
if( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
{
msg << "Service : client accept Warning. [" << errno << "]["
<< strerror(errno) << "][Port : " << m_port << ",PID:" << pid << "]";
LOGACONSOLE(LDBG, msg);
continue;
}
// 오류발생시 해당 내역 로깅처리.
msg << "Service : client accept failed. [" << errno << "]["
<< strerror(errno) << "][Port : " << m_port << ",PID:" << pid << "]";
LOGACONSOLE(LERR, msg);
}
else
{
// 정상적인 Client 인 경우
msg << "Client..... [PID :" << pid << "]";
LOGACONSOLE(LDBG, msg);
#ifdef AF_INET6
char tempBuffer[INET6_ADDRSTRLEN] = {0};
#else //AF_INET6
char tempBuffer[INET_ADDRSTRLEN] = {0};
#endif // AF_INET6
#ifdef AF_INET6
if(m_ipv6)
{
if( inet_ntop( AF_INET6, (void *)&clientSockAddrv6.sin6_addr, tempBuffer, sizeof(tempBuffer)) != NULL )
{
LOG( LDBG, "Client Info(v6) : %s",tempBuffer);
}
else
{
LOG( LERR, "inet_ntop(v6) error[%d][%s]", errno, strerror(errno) );
}
}
else
#endif //AF_INET6
{
if( inet_ntop( AF_INET, (void *)&clientSockAddr.sin_addr, tempBuffer, sizeof(tempBuffer)) != NULL )
{
LOG( LDBG, "Client Info : %s",tempBuffer);
}
else
{
LOG( LERR, "inet_ntop error[%d][%s]", errno, strerror(errno) );
}
}
// work
CWorkThread *work = m_WokrPool.GetWork();
if(work)
{
work->RunWork(nClientfd, tempBuffer);
}
else
{
msg << "Failed Work pool allocation.[IP :" << tempBuffer << "]";
LOGACONSOLE(LERR, msg);
::close(nClientfd);
}
}
}
return true;
}
bool CTCPService::Start()
{
ostringstream msg;
msg << "TCP Service START.";
LOGACONSOLE(LDEV1, msg);
Accpet();
msg << "TCP Service END.";
LOGACONSOLE(LDEV1, msg);
return true;
}
bool CTCPService::Stop()
{
CService::Stop();
return true;
}
// Abstract Factory returning a Service
CService* CServiceFactory::CreateSerivce(SERVICE_TYPE::sType t)
{
CService * r = NULL;
switch(t)
{
case SERVICE_TYPE::FAIL_MON:
r = new CFailLogMon;
break;
case SERVICE_TYPE::TCP_SERVICE:
r = new CTCPService;
break;
case SERVICE_TYPE::UNSET:
default:
LOG(LERR, "Service Type is unknown.");
break;
}
_LOG( LDEV, "Service Factory Type = [%d]", t);
return r;
}
+94
View File
@@ -0,0 +1,94 @@
/***************************************************************************
Service Class Header ( Service.h )
-----------------------------------------
begin : 2013/05/30
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/30 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __SERVICE_H__
#define __SERVICE_H__
#include "WorkPool.h"
#include "DBManager.h"
namespace SERVICE_TYPE
{
enum sType {
UNSET = -1,
FAIL_MON = 0,
TCP_SERVICE = 1,
};
}
class CService
{
public:
CService() : m_done(false) {};
virtual ~CService() {};
virtual bool Create();
virtual bool Start();
virtual bool Stop();
protected:
CWorkPool m_WokrPool;
CDBManager m_DBManager;
bool m_done;
};
class CFailLogMon : public CService
{
public:
CFailLogMon();
virtual ~CFailLogMon();
virtual bool Create();
virtual bool Start();
virtual bool Stop();
protected:
bool FindLog();
string m_fiallogpath;
};
class CTCPService : public CService
{
public:
CTCPService();
virtual ~CTCPService();
virtual bool Create();
virtual bool Start();
virtual bool Stop();
protected:
bool Accpet();
public:
static bool MakeListenSocket();
static void SetPort(int port);
protected:
static int m_port;
static int m_listenSocket;
static bool m_ipv6;
};
// Abstract Factory returning a Service
class CServiceFactory
{
public:
CService* CreateSerivce(SERVICE_TYPE::sType t);
};
#endif // __SERVICE_H__
+78
View File
@@ -0,0 +1,78 @@
/***************************************************************************
Signal Function (Signals.cpp )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : svc1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Signals.h"
#include "Logger.h"
void SetSighandler(int signum, signal_handler_t handler, int flag)
{
sigset_t set;
sigfillset( &set );
sigprocmask( SIG_SETMASK, &set, NULL ); /* 신호 처리기 처리 설정 위한 블록 */
int ret;
struct sigaction oldact;
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = handler;
sigfillset(&act.sa_mask);
act.sa_flags = flag;
ret = sigaction(signum, &act, &oldact);
if (ret != 0) {
char buf[1024];
snprintf(buf, sizeof(buf), "SetSighandler: sigaction returned "
"%d when trying to install a signal handler for %s\n",
ret, sys_siglist[signum]);
cerr << buf << endl;
LOG( LERR, "[PID:%d] %s", getpid(), buf);
exit(EXIT_FAILURE);
}
sigemptyset(&set); /* 신호 처리기 처리 설정 위한 블록 해제 */
sigprocmask(SIG_SETMASK, &set, NULL);
}
void SetIgnoreSignal(bool isDaemon)
{
SetSighandler(SIGPIPE, SIG_IGN, 0); // 파이프 디스크립터 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정
SetSighandler(SIGHUP, SIG_IGN, 0); // Process를 기동시킨 관리자의 로그아웃시 발생 시그널
SetSighandler(SIGQUIT, SIG_IGN, 0); // 키보드에 의한 Abort 신호 처리 => ?
if(isDaemon == true)
{
SetSighandler(SIGINT, SIG_IGN, 0); // ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음
}
}
void SetSIGCHLD(signal_handler_t handler)
{
SetSighandler(SIGCHLD, handler, 0);
}
void SetSIGTERM(bool isDaemon, signal_handler_t handler)
{
SetSighandler(SIGTERM, handler, 0);
if (isDaemon == false)
{
#ifdef _DEBUG
cout << "SetSIGTERM Console : set SIGINT" << endl;
#endif // _DEBUG
SetSighandler(SIGINT, handler, 0);
}
}
+29
View File
@@ -0,0 +1,29 @@
/***************************************************************************
Signal Function Header ( Signals.h )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : svc1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __SIGNAL_FUNCTION_H__
#define __SIGNAL_FUNCTION_H__
typedef void (*signal_handler_t)(int);
extern void SetSighandler(int signum, signal_handler_t handler, int flag);
extern void SetIgnoreSignal(bool isDaemon);
extern void SetSIGCHLD(signal_handler_t handler);
extern void SetSIGTERM(bool isDaemon, signal_handler_t handler);
#endif // __SIGNAL_FUNCTION_H__
+181
View File
@@ -0,0 +1,181 @@
/***************************************************************************
Work Class (Work.cpp)
-----------------------------------------
begin : 2013/07/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Work.h"
#include "Configs.h"
#include "Logger.h"
#define SOCKET_TIMEOUT 5
// class CWorkFile
CWorkFile::CWorkFile()
{
}
CWorkFile::CWorkFile(string & path)
: m_path(path)
{
}
CWorkFile::~CWorkFile()
{
DeleteWorkFile();
}
void CWorkFile::DeleteWorkFile()
{
::unlink(m_path.c_str());
}
bool CWorkFile::ReadWorkFile(string & data)
{
ifstream ifs;
ifs.open(m_path.c_str());
if (ifs.is_open())
{
string t;
while(!ifs.eof())
{
getline(ifs, t);
data.append(t);
t.clear();
}
ifs.close();
ostringstream msg;
msg << "Read File : Data";
LOGACONSOLE(LDBG, msg);
msg << "################ Data Start ################";
LOGACONSOLE(LDBG, msg);
msg << "################ Text ################" << endl;
msg << data;
LOGACONSOLE(LDBG, msg);
msg << "################ Binary ################";
LOGACONSOLE(LDEV, msg);
_LOG_HEX_(LDEV, data.c_str(), data.size());
msg << "################ Data End ################";
LOGACONSOLE(LDBG, msg);
}
else
{
// show message:
LOG(LERR,"Error opening file %s", m_path.c_str());
return false;
}
return true;
}
// class CWorkSocket
CWorkSocket::CWorkSocket()
: CBaseSocket( SOCKET_NOT_VALID )
{
}
CWorkSocket::CWorkSocket(const int & sfd)
: CBaseSocket( sfd )
{
}
CWorkSocket::~CWorkSocket()
{
Close();
}
int CWorkSocket::SetOption()
{
if( m_sock == SOCKET_NOT_VALID )
return -1;
int result = 0;
/* Time wait ¹æÁö */
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 10; /* 0 for abortive disconnect */
result = setsockopt(m_sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_LINGER set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
struct timeval tv_timeo = { SOCKET_TIMEOUT, 0 };
/* Recv Timeout ¼³Á¤. */
result = setsockopt( m_sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_RCVTIMEO set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
/* Send Timeout ¼³Á¤. */
result = setsockopt( m_sock, SOL_SOCKET, SO_SNDTIMEO, &tv_timeo, sizeof(tv_timeo));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_SNDTIMEO set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
return 0;
}
ssize_t CWorkSocket::ReadHead(int & bodysize)
{
ssize_t r = 0;
r = ReadNTimeout(&bodysize, sizeof(bodysize));
if(r > 0)
bodysize = ntohl(bodysize);
ostringstream msg;
msg << "Read Socket : Header Data [" << bodysize << "]";
LOGACONSOLE(LDBG, msg);
return r;
}
ssize_t CWorkSocket::ReadBody(string & data)
{
ssize_t r = 0;
r = ReadNTimeout( const_cast<char*>(data.c_str()), data.size());
ostringstream msg;
msg << "Read Socket : Body Data";
LOGACONSOLE(LDBG, msg);
msg << "################ Data Start ################";
LOGACONSOLE(LDBG, msg);
msg << "################ Text ################" << endl;
msg << data;
LOGACONSOLE(LDBG, msg);
msg << "################ Binary ################";
LOGACONSOLE(LDEV, msg);
_LOG_HEX_(LDEV, data.c_str(), data.size());
msg << "################ Data End ################";
LOGACONSOLE(LDBG, msg);
return r;
}
+47
View File
@@ -0,0 +1,47 @@
/***************************************************************************
Work Class Header ( Work.h )
-----------------------------------------
begin : 2013/07/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/07/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __WORK_H__
#define __WORK_H__
#include "BaseSocket.h"
class CWorkFile
{
public:
CWorkFile();
CWorkFile(string & path);
virtual ~CWorkFile();
void DeleteWorkFile();
bool ReadWorkFile(string & data);
private:
string m_path;
};
class CWorkSocket : public CBaseSocket
{
public:
CWorkSocket();
CWorkSocket(const int & sfd);
virtual ~CWorkSocket();
int SetOption();
ssize_t ReadHead(int & bodysize);
ssize_t ReadBody(string & data);
};
#endif // __WORK_H__
+973
View File
@@ -0,0 +1,973 @@
/***************************************************************************
Work Pool Class (WorkPool.cpp)
-----------------------------------------
begin : 2013/06/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/06/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "WorkPool.h"
#include "DataDefine.h"
#include "DBManager.h"
#include "Work.h"
#include "InsertData.h"
#include "Configs.h"
#include "Logger.h"
// class CWorkThread
CWorkThread::CWorkThread()
: m_datatype(CWorkThread::UNKNOWN), m_clientfd(SOCKET_NOT_VALID), m_stop(false),
m_dbManager(NULL), m_pools(NULL), m_key(0)
{
pthread_mutex_init(&m_lock, NULL);
pthread_cond_init(&m_cond, NULL);
}
CWorkThread::~CWorkThread()
{
m_stop = true;
pthread_mutex_destroy(&m_lock);
pthread_cond_destroy(&m_cond);
}
void CWorkThread::WaitSignal()
{
_LOG(LDEV, "Work Thread[%u] Waiting...", (unsigned int)pthread_self());
pthread_mutex_lock(&m_lock);
pthread_cond_wait(&m_cond, &m_lock);
pthread_mutex_unlock(&m_lock);
}
void* CWorkThread::WorkFn( void* pdata )
{
CWorkThread* pObject = reinterpret_cast<CWorkThread *>(pdata);
_LOG(LDEV1, "Work Thread[%u] Start..", (unsigned int)pthread_self());
while(!pObject->m_stop)
{
// 신호가 도착하면 현재 처리해야할 소켓(or 파일)로부터 데이터 읽음
pObject->WaitSignal();
// run
pObject->Running();
// complete
pObject->Completed();
}
_LOG(LDEV1, "Work Thread[%u] End.", (unsigned int)pthread_self());
return 0;
}
bool CWorkThread::CreateWorkThread( CWorkPool* pools, CDBManager * manager )
{
pthread_t workthread;
m_pools = pools;
m_dbManager = manager;
int ret = pthread_create(&workthread, 0, CWorkThread::WorkFn, (void*)this);
if (ret != 0)
{
ostringstream msg;
msg << "Work Thread create failed.[" << errno << "]";
LOGACONSOLE(LERR, msg);
return false;
}
sleep(0);
return true;
}
bool CWorkThread::ReadFromSocket()
{
CWorkSocket s(m_clientfd);
int r = 0;
int nBodySize = 0;
s.SetOption();
// read head
if((r = s.ReadHead(nBodySize)) <= 0 )
{
LOG(LERR, "Failed to read header.[%d][%s]", r, m_clientip.c_str());
return false;
}
m_readdata.resize(nBodySize);
// read body
if((r = s.ReadBody(m_readdata)) <= 0 )
{
LOG(LERR, "Failed to read body.[read size: %d][%s]", r, m_clientip.c_str());
return false;
}
return true;
}
bool CWorkThread::ReadFromFile()
{
CWorkFile f(m_filename);
if(!f.ReadWorkFile(m_readdata))
return false;
return true;
}
bool CWorkThread::ReadData()
{
bool r = true;
LOG(LDEV1, "Setp 1. Read Data.");
switch(m_datatype)
{
case CWorkThread::SOCKET_DATA:
LOG(LDEV1, "Socket data.");
r = ReadFromSocket();
break;
case CWorkThread::FILE_DATA:
LOG(LDEV1, "File data.");
r = ReadFromFile();
break;
case CWorkThread::UNKNOWN:
default:
r = false;
LOG(LERR, "Unknown data.");
break;
}
return r;
}
bool CWorkThread::GetServiceInfo(const Node* node, InsertDataMap::iterator &iter)
{
ostringstream msg;
const Element* ext = dynamic_cast<const Element*>(node);
if( ext )
{
string svcRC = ext->get_attribute_value(XML_SVC_RC);
string svcUserSEQ = ext->get_attribute_value(XML_SVC_USER_SEQ);
string svcSEQ = ext->get_attribute_value(XML_SVC_SEQ);
string svcName = ext->get_attribute_value(XML_SVC_NAME);
if(svcRC.empty())
{
msg << "XML Parser error. Service "XML_SVC_RC" empty.";
LOGACONSOLE(LERR, msg);
return false;
}
if(svcUserSEQ.empty())
{
msg << "XML Parser error. Service "XML_SVC_USER_SEQ" empty.";
LOGACONSOLE(LERR, msg);
return false;
}
if(svcSEQ.empty())
{
msg << "XML Parser error. Service "XML_SVC_SEQ" empty.";
LOGACONSOLE(LERR, msg);
return false;
}
// 2013-11-15 : 신규 rc_statd 에서 해당 정보 보낼 수 없으므로 해당 체크 기능 삭제
//if(svcName.empty())
//{
// msg << "XML Parser error. Service "XML_SVC_NAME" empty.";
// LOGACONSOLE(LERR, msg);
// return false;
//}
multimap<string,CInsertData>::iterator it;
iter = m_insertdata.insert(pair<string, CInsertData>
(svcSEQ, CInsertData(svcRC, svcUserSEQ, svcSEQ, svcName)));
}
else
{
msg << "XML Parser error. Service attributes error.";
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
bool CWorkThread::GetXNLElementValue(const Node* node, string elmentName, string & ret)
{
xmlpp::Node* n;
if( elmentName.empty() )
{
n = const_cast<xmlpp::Node*>(node);
}
else
{
n = node->get_children(elmentName).front();
if( n == NULL || node->get_children(elmentName).size() == 0 )
return false;
}
const xmlpp::Element* nodeElement = dynamic_cast<const Element*>(n);
if(nodeElement)
{
const TextNode* nodetext = nodeElement->get_child_text();
if(nodetext)
{
ret = nodetext->get_content();
}
else
{
// 항목은 있으나 값이 없는 경우
LOG(LNOT, "XML %s value of the item does not exist. And the default(0) value is set.", elmentName.c_str());
ret = "0";
}
}
else
{
return false;
}
return true;
}
bool CWorkThread::GetStatValue(string statType, const Node* node, InsertDataMap::iterator &it)
{
string slist;
// Data Extraction do list
if(statType.compare(XML_STAT_ACCESS) == 0)
slist = XML_STAT_ACCESS_VALUE_LIST;
else if (statType.compare(XML_STAT_STORAGE) == 0)
slist = XML_STAT_STORAGE_VALUE_LIST;
else if (statType.compare(XML_STAT_NETWORK) == 0)
slist = XML_STAT_NETWORK_VALUE_LIST;
else if (statType.compare(XML_STAT_TRANSFER) == 0)
slist = XML_STAT_TRANSFER_VALUE_LIST;
else
{
LOG(LERR, "XML Parser error. Unknown STAT type.");
return false;
}
_LOG(LDEV1, "STAT items %s", slist.c_str());
vector< string > vec;
StringSplit(slist, ",", vec, false);
if(vec.size() < 1)
{
LOG(LERR, "STAT Items extraction failed.");
return false;
}
// Data Extraction
string v;
for (vector<string>::iterator iter = vec.begin() ; iter != vec.end(); ++iter)
{
if( GetXNLElementValue(node, *iter, v) == false)
{
LOG(LERR, "XML Parser error. STAT %s Items %s empty."
, statType.c_str(), (*iter).c_str());
return false;
}
LOG(LDEV, "XML %s Value : %s = %s",
statType.c_str(), (*iter).c_str(), v.c_str());
if( it->second.SetStat(*iter, v) == false)
{
LOG(LERR, "XML Parser error. STAT %s Items %s duplicate."
, statType.c_str(), (*iter).c_str());
return false;
}
}
return true;
}
bool CWorkThread::GetStatTimeValue(string statType, const Node* node, InsertDataMap::iterator &iter)
{
ostringstream msg;
const Element* ext = dynamic_cast<const Element*>(node);
if(ext)
{
// get Time attribute
string svctime = ext->get_attribute_value(XML_STAT_TIME);
msg << "XML DATA : STAT " << statType << " TIME = " << svctime;
LOGACONSOLE(LDEV1, msg);
if( svctime.empty() )
{
msg << "XML Parser error. " << statType << " time value empty.";
LOGACONSOLE(LERR, msg);
return false;
}
iter->second.MakeStatKey(statType, svctime);
if( iter->second.SetStat(XML_STAT_TIME, svctime) == false)
{
msg << "XML Parser error. " << statType << " time value duplicate.";
LOGACONSOLE(LERR, msg);
return false;
}
}
else
{
msg << "XML Parser error. " << statType << " attribute empty.";
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
int CWorkThread::GetStatSubData(string statType, const Node* node, InsertDataMap::iterator &it)
{
ostringstream msg;
// statType : ACCESS, STORAGE, NETWORK, TRANSFER
Node::NodeList list = node->get_children(statType);
msg << "XML DATA : STAT " << statType << " Data size = " << list.size();
LOGACONSOLE(LDBG, msg);
for(Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
{
msg << "XML DATA : STAT " << statType <<" Index[" << distance(list.begin(), iter)
<< "],[" << (*iter)->get_name() <<"]";
LOGACONSOLE(LDEV1, msg);
// TIME
if(GetStatTimeValue(statType, *iter, it) == false)
return -1;
// value
if(GetStatValue(statType, *iter, it) == false)
return -1;
it->second.ClearKey();
}
return list.size();
}
bool CWorkThread::GetStatSubList(const Node* node, InsertDataMap::iterator &iter)
{
int r = 0, n = 0;
// ACCESS
n = GetStatSubData(XML_STAT_ACCESS, node, iter);
if(n < 0 ) return false;
r += n;
// STORAGE
n = GetStatSubData(XML_STAT_STORAGE, node, iter);
if(n < 0 ) return false;
r += n;
// NETWORK
n = GetStatSubData(XML_STAT_NETWORK, node, iter);
if(n < 0 ) return false;
r += n;
// TRANSFER
n = GetStatSubData(XML_STAT_TRANSFER, node, iter);
if(n < 0 ) return false;
r += n;
if( r == 0 )
{
LOG(LERR, "XML Parser error. %s data empty.", XML_STAT);
}
return (r > 0);
}
bool CWorkThread::GetStatData(const Node* node, InsertDataMap::iterator &it)
{
bool r = true;
ostringstream msg;
Node::NodeList statlist = node->get_children(XML_STAT);
msg << "XML DATA : STAT Total = " << statlist.size();
LOGACONSOLE(LDEV, msg);
if( statlist.size() < 1)
{
r = false;
msg << "XML Parser error. " XML_STAT " empty.";
LOGACONSOLE(LERR, msg);
}
unsigned int success = 0;
for(Node::NodeList::iterator iter = statlist.begin(); iter != statlist.end(); ++iter)
{
msg << "XML DATA : STAT Index[" << distance(statlist.begin(), iter)
<< "],[" << (*iter)->get_name() <<"]";
LOGACONSOLE(LDEV1, msg);
// ACCESS, STORAGE, NETWORK, TRANSFER
if(GetStatSubList(*iter, it) == false)
{
r = false;
break;
}
++ success;
}
if(success != statlist.size())
{
msg << "XML Parser error. STAT Total(" << statlist.size()
<< ")/Success(" << success << ")";
LOGACONSOLE(LERR, msg);
}
return r;
}
bool CWorkThread::GetFailDatabaseType(const Node* node, InsertDataMap::iterator &it)
{
ostringstream msg;
const Element* ext = dynamic_cast<const Element*>(node);
if(ext)
{
// get Time attribute
string failtype = ext->get_attribute_value(XML_FAIL_TYPE);
msg << "XML DATA : FAIL DATABASE TYPE = " << failtype;
LOGACONSOLE(LDEV1, msg);
if( failtype.empty() )
{
msg << "XML Parser error. "XML_FAIL_DATABASE" "XML_FAIL_TYPE " value empty.";
LOGACONSOLE(LERR, msg);
return false;
}
it->second.SetFailType(failtype);
}
else
{
msg << "XML Parser error. "XML_FAIL_DATABASE" attribute empty.";
LOGACONSOLE(LERR, msg);
return false;
}
return true;
}
bool CWorkThread::GetFailDatabaseList(const Node* node, InsertDataMap::iterator &it)
{
ostringstream msg;
Node::NodeList list = node->get_children(XML_FAIL_DATABASE);
if( list.size() < 1 )
{
msg << "XML Parser error. " XML_FAIL_DATABASE " etmpy.";
LOGACONSOLE(LERR, msg);
return false;
}
msg << "XML DATA : FAIL Data size = " << list.size();
LOGACONSOLE(LDBG, msg);
for(Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
{
// TYPE
if(GetFailDatabaseType(*iter, it) == false)
return false;
}
return true;
}
bool CWorkThread::GetFailData(const Node* node, InsertDataMap::iterator &it)
{
ostringstream msg;
// FAIL
Node::NodeList faillist = node->get_children(XML_FAIL);
msg << "Fail Cnt = " << faillist.size();
LOGACONSOLE(LDEV, msg);
if( faillist.size() < 1)
{
msg << "XML "XML_FAIL" empty.";
LOGACONSOLE(LDBG, msg);
}
for(Node::NodeList::iterator iter = faillist.begin(); iter != faillist.end(); ++iter)
{
// DATABASE
msg << "XML DATA : FAIL Index[" << distance(faillist.begin(), iter)
<< "],[" << (*iter)->get_name() <<"]";
LOGACONSOLE(LDEV1, msg);
if( GetFailDatabaseList(*iter, it) == false )
return false;
}
return true;
}
bool CWorkThread::DataParsing(Document *doc)
{
ostringstream msg;
if(!doc)
{
msg << "XML Parser error. Document is NULL.";
LOGACONSOLE(LERR, msg);
return false;
}
Element *root = doc->get_root_node();
if(!root)
{
msg << "XML Parser error. ROOT is NULL.";
LOGACONSOLE(LERR, msg);
return false;
}
// check root
if(root->get_name() != XML_STR_ROOT)
{
msg << "XML Parser error. XML root node different.["
<< root->get_name() << "," << XML_STR_ROOT <<"]";
LOGACONSOLE(LERR, msg);
return false;
}
// check service
Node::NodeList svclist = root->get_children(XML_SVC);
if( svclist.size() < 1 )
{
msg << "XML Parser error. XML "XML_SVC" empty.";
LOGACONSOLE(LERR, msg);
return false;
}
bool r = true;
// service list
for(Node::NodeList::iterator iter = svclist.begin(); iter != svclist.end(); ++iter)
{
InsertDataMap::iterator it;
// get service attribute
if(GetServiceInfo(*iter, it) == false )
{
r = false;
break;
}
msg << "Service Info : RC("<< it->second.GetRC() <<"),UserSEQ("
<< it->second.GetUserSEQ() <<"),";
msg << "Service SEQ("<< it->second.GetSvcSEQ() <<"),Service Name("
<< it->second.GetSvcName() << ")";
LOGACONSOLE(LDEV, msg);
// get stat
if( GetStatData(*iter, it) == false )
{
r = false;
break;
}
// get fail
if( GetFailData(*iter, it) == false )
{
r = false;
break;
}
}
return r;
}
bool CWorkThread::XMLParser()
{
bool r = true;
ostringstream msg;
DomParser parser;
LOG(LDEV1, "Setp 2. XML Parser.");
try
{
parser.set_substitute_entities(); //We just want the text to be resolved/unescaped automatically.
parser.parse_memory(m_readdata);
if(parser)
{
r = DataParsing(parser.get_document());
}
else
{
r = false;
msg << "XML Parser error. Parser is NULL";
LOGACONSOLE(LERR, msg);
}
}
catch(const std::exception& ex)
{
r = false;
msg << "XML Parser error. Exception caught: " << ex.what();
LOGACONSOLE(LERR, msg);
}
if( r != true )
{
msg << "XML DATA : START " << endl;
msg << m_readdata;
msg << "XML DATA : END " << endl;
LOGACONSOLE(LERR, msg);
}
return r;
}
void CWorkThread::SetUsedDB(CInsertData &idata, vector<string> & odata)
{
int n = idata.FailTypeSize();
if( n > 0 )
{
for(int i = 0; i < n; ++i)
{
string k = idata.GetFailType(i);
if( CMyConfig::GetInstance()->FindUsedDBType(k) == false )
{
LOG(LWAR, "It is not in the database type a value of '%s'",
k.c_str());
}
else
{
odata.push_back(k);
}
}
}
else
{
n = CMyConfig::GetInstance()->GetUsedDBTypeCnt();
for(int i = 0; i < n; ++i)
{
odata.push_back(CMyConfig::GetInstance()->GetUsedDBType(i));
}
}
}
bool CWorkThread::InsertData()
{
LOG(LDEV1, "Setp 3. Insert Data.");
for( InsertDataMap::iterator it = m_insertdata.begin(); it != m_insertdata.end(); ++it)
{
#ifdef _DEBUG
it->second.PrintStatAll();
#endif // _DEBUG
// 삽입할 데이데 베이스 종류 정의
vector<string> usedDbType;
SetUsedDB(it->second, usedDbType);
if( usedDbType.empty() )
{
LOG(LNOT, "Type of database that you want to insert the data does not exist.");
continue;
}
// insert
for(unsigned int i = 0; i < usedDbType.size(); ++i)
{
LOG(LDEV1, "Used DB Type %s", usedDbType[i].c_str());
it->second.ClearJobLog();
it->second.MakeInsertFailKey(usedDbType[i]);
it->second.ExecuteInsert(usedDbType[i], m_dbManager);
_LOG(LINF, "Work Log: [%s] [%s] => SUCCESS: %s, FAIL: %s", usedDbType[i].c_str(),
it->second.GetSvcSEQ(), it->second.GetSuccess(), it->second.GetFail())
}
}
return true;
}
int CWorkThread::WriteFailLog()
{
LOG(LDEV1, "Setp 4. Write Fail Log.");
ostringstream msg;
try
{
Document document;
// CCSTAT
Element* nodeRoot = document.create_root_node(XML_STR_ROOT, "", "");
for( InsertDataMap::iterator it = m_insertdata.begin(); it != m_insertdata.end(); ++it)
{
#ifdef _DEBUG
it->second.PrintInsertFailAll();
#endif // _DEBUG
it->second.MakeXMLNode( nodeRoot );
}
Node::NodeList faillist = nodeRoot->get_children();
// save fail xml
if(faillist.size() > 0)
{
int key = rand() %10000;
// Get Current Data & Time
time_t now = time( NULL );
struct tm timeNow;
localtime_r( &now, &timeNow );
char failname[255] = {0};
// 로그 파일명 규칙 : cc_statd_YYYYMMDDHHmmSS_RandomKey.xml
sprintf(failname, "%s/%s_%04d%02d%02d%02d%02d%02d_%04d.xml"
, CMyConfig::GetInstance()->GetFailLogPath(), PROG_NAME
, timeNow.tm_year+1900, timeNow.tm_mon+1, timeNow.tm_mday
, timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec, key);
_LOG(LINF, "Save Fail xml : %s", failname);
document.write_to_file(failname);
return 1;
}
}
catch(const std::exception& ex)
{
msg << "Exception caught: " << ex.what();
LOGACONSOLE(LERR, msg);
return -1;
}
return 0;
}
void CWorkThread::Running()
{
if(m_stop) return;
int nstep = 0;
bool success = false, stepend = false;
_LOG(LDBG, "Work Thread[%u] Running...", (unsigned int)pthread_self());
do
{
++nstep;
switch(nstep)
{
case 1: // read data
success = ReadData();
break;
case 2: // XML Parser
success = XMLParser();
break;
case 3: // insert data
success = InsertData();
break;
case 4: // write fail log
stepend = true;
// 부분 오류를 대비하여 fail로그 작업이 있다면
// 현재 요청에 대해서 실패로 처리함
success = (WriteFailLog() == 0) ? true : false;
break;
default:
success = false;
LOG(LERR, "Unknown job step.");
break;
}
LOG(LDBG, "Work Thread[%u] : Setp %d => Result %d",
(unsigned int)pthread_self(), nstep, success);
if(stepend)
break;
} while (success);
// write log
if(success)
{
LOG(LINF, "Work Success. [%s]"
, (m_clientip.empty() ? m_filename.c_str() : m_clientip.c_str()));
}
else
{
LOG(LERR, "Work Fail. [%s]"
, (m_clientip.empty() ? m_filename.c_str() : m_clientip.c_str()));
}
}
void CWorkThread::Completed()
{
if(m_stop) return;
_LOG(LDEV, "Work Thread[%u] Completion.", (unsigned int)pthread_self());
m_datatype = CWorkThread::UNKNOWN;
m_filename.clear();
m_clientip.clear();
m_clientfd = SOCKET_NOT_VALID;
m_readdata.clear();
m_insertdata.clear();
ReleasePool();
}
void CWorkThread::Stop()
{
_LOG(LDEV1, "Work Thread[%u] Stop.", (unsigned int)pthread_self());
m_stop = true;
pthread_cond_signal(&m_cond);
pthread_join(pthread_self(), NULL);
}
void CWorkThread::RunWork(int client, string ipstr)
{
if(m_stop) return;
m_datatype = CWorkThread::SOCKET_DATA;
m_clientfd = client;
m_clientip = ipstr;
pthread_cond_signal(&m_cond);
}
void CWorkThread::RunWork(string path)
{
if(m_stop) return;
m_datatype = CWorkThread::FILE_DATA;
m_filename = path;
pthread_cond_signal(&m_cond);
}
void CWorkThread::ReleasePool()
{
if(m_stop) return;
if(m_pools)
{
m_pools->ReleaseWork(this);
}
}
// class CWorkPool
CWorkPool::CWorkPool()
: m_size(0), m_exit(false)
{
pthread_mutex_init(&m_lock, NULL);
}
CWorkPool::~CWorkPool()
{
Finalized();
pthread_mutex_destroy(&m_lock);
}
void CWorkPool::Finalized()
{
if(m_exit) return;
m_exit = true;
_LOG(LDEV1, "Work Pool Finalized.");
multimap<int, CWorkThread*>::iterator mi;
mi = m_pools.begin();
while(mi != m_pools.end())
{
mi->second->Stop();
delete mi->second;
mi ++;
}
m_pools.clear();
}
bool CWorkPool::CreatePool(int size, CDBManager * manager)
{
_LOG(LDBG, "Work Threand CNT = %d", size);
srand(time( NULL));
m_size = size;
for (int i = 0; i < m_size; i++)
{
CWorkThread * work = new CWorkThread();
if(work)
{
if(work->CreateWorkThread(this, manager) == false)
return false;
m_pools.insert( pair<int, CWorkThread*>(0, work));
}
else
{
LOG(LERR, "Failed Work Thread allocation.");
return false;
}
}
return true;
}
CWorkThread* CWorkPool::GetWork()
{
CWorkThread *p = NULL;
while( !m_exit && p == NULL )
{
pthread_mutex_lock(&m_lock);
multimap<int, CWorkThread*>::iterator it;
it = m_pools.begin();
if( it->first )
{
LOG(LNOT, "Work Pool Full.[PID %d]", getpid());
pthread_mutex_unlock(&m_lock);
sleep(1);
}
else
{
int key = rand() %100 +1;
p =it->second;
m_pools.erase(it);
it = m_pools.insert(pair<int, CWorkThread*>(key, p));
LOG(LDEV, "Get Work Key [%d]", key);
p->SetPoolKey(key);
pthread_mutex_unlock(&m_lock);
}
}
return p;
}
void CWorkPool::ReleaseWork(CWorkThread * work )
{
pthread_mutex_lock(&m_lock);
pair <multimap<int, CWorkThread*>::iterator, multimap<int, CWorkThread*>::iterator> ret;
ret = m_pools.equal_range(work->GetPoolKey());
LOG(LDEV, "Release Work Key [%d]", work->GetPoolKey());
for (multimap<int, CWorkThread*>::iterator it=ret.first; it!=ret.second; ++it)
{
if( it->second == work )
{
m_pools.erase(it);
m_pools.insert(pair<int, CWorkThread*>(0, work));
break;
}
}
pthread_mutex_unlock(&m_lock);
}
+119
View File
@@ -0,0 +1,119 @@
/***************************************************************************
Work Pool Class Header ( WorkPool.h )
-----------------------------------------
begin : 2013/06/04
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/06/04 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __WORK_POOL_H__
#define __WORK_POOL_H__
class CDBManager;
class CWorkPool;
class CInsertData;
class CWorkThread
{
public:
CWorkThread();
~CWorkThread();
bool CreateWorkThread( CWorkPool* pools, CDBManager * manager );
void Running();
void Completed();
void Stop();
void RunWork(int client, string ipstr);
void RunWork(string path);
inline void SetPoolKey(int key) { m_key = key; }
inline int GetPoolKey() {return m_key; }
protected:
void WaitSignal();
void ReleasePool();
bool ReadFromSocket();
bool ReadFromFile();
bool GetXNLElementValue(const Node* node, string elmentName, string & ret);
typedef multimap< string, CInsertData > InsertDataMap;
bool GetServiceInfo(const Node* node, InsertDataMap::iterator &iter);
bool GetStatData(const Node* node, InsertDataMap::iterator &iter);
bool GetStatSubList(const Node* node, InsertDataMap::iterator &iter);
int GetStatSubData(string statType, const Node* node, InsertDataMap::iterator &iter);
bool GetStatTimeValue(string statType, const Node* node, InsertDataMap::iterator &iter);
bool GetStatValue(string statType, const Node* node, InsertDataMap::iterator &iter);
bool GetFailData(const Node* node, InsertDataMap::iterator &iter);
bool GetFailDatabaseList(const Node* node, InsertDataMap::iterator &iter);
bool GetFailDatabaseType(const Node* node, InsertDataMap::iterator &iter);
bool DataParsing(Document *doc);
void SetUsedDB(CInsertData &idata, vector<string> & odata);
bool ReadData();
bool XMLParser();
bool InsertData();
int WriteFailLog();
private:
static void* WorkFn(void*);
enum WORK_DATA {
UNKNOWN = -1,
SOCKET_DATA = 0,
FILE_DATA = 1,
};
enum WORK_DATA m_datatype;
int m_clientfd;
string m_clientip;
string m_filename;
pthread_mutex_t m_lock;
pthread_cond_t m_cond;
bool m_stop;
CDBManager* m_dbManager;
CWorkPool* m_pools;
int m_key;
string m_readdata;
InsertDataMap m_insertdata;
};
class CWorkPool
{
public:
CWorkPool();
~CWorkPool();
bool CreatePool(int size, CDBManager * manager);
void Finalized();
CWorkThread* GetWork();
void ReleaseWork(CWorkThread * work);
protected:
private:
int m_size;
bool m_exit;
pthread_mutex_t m_lock;
multimap<int, CWorkThread*> m_pools;
};
#endif // __WORK_POOL_H__
+195
View File
@@ -0,0 +1,195 @@
/***************************************************************************
cc_statd Worker ( Worker.cpp )
-----------------------------------------
begin : 2013/05/30
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/30 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "cc_statd.h"
#include "Worker.h"
#include "Signals.h"
#include "Configs.h"
#include "Service.h"
#include "Logger.h"
static int _isExit = 0;
static pid_t _FailMonPid = -1;
static pid_t _MainPid = -1;
static CService * _WorkService = NULL;
static void SigTermWorker( int nSignalNumber )
{
if(_isExit) return;
_isExit = 1;
if(_WorkService)
_WorkService->Stop();
ostringstream msg;
// Signal Number 에 따른 로깅처리.
if( nSignalNumber == SIGTERM )
{
msg << "Worker Process [" << getpid() << "] exit job start by user signal [SIGTERM]";
}
else
{
msg << "Worker Process [" << getpid() << "] exit job start by user signal ["<< nSignalNumber <<"]";
}
cout << msg.str() << endl;
_LOG(LWAR, msg.str().c_str());
}
/// @brief Worker Process 의 main 함수
static int WorkerMain( bool isDaemon, CService * s)
{
// Set Signal Handler
SetIgnoreSignal(isDaemon);
SetSIGTERM(isDaemon, SigTermWorker);
_WorkService = s;
// service start
if(s->Create())
s->Start();
else
_isExit = 2;
// signal wait
while ( _isExit == 0 )
{
#ifdef _DEBUG
cout << "Working ..." << endl;
#endif //_DEBUG
pause();
}
// service stop
s->Stop();
if( _isExit > 1 )
{
// The main process exit process
LOG( LERR, "Worker process create failed. Exit...");
kill(_MainPid, SIGTERM);
}
_LOG( LWAR, "Worker Process[%d] exit.. Good Bye..", getpid());
CLogger::Exit();
CMyConfig::Exit();
// 잠시 대기 후 종료처리.
usleep(500000);
return (_isExit == 1 ? EXIT_SUCCESS: EXIT_FAILURE);
}
/// TCP Process
static void MakeTCPProcess( bool isDaemon )
{
pid_t processId;
// Worker 프로세스 fork
processId = fork();
if( processId < 0 ) // Fork fail
{
int errorNum = errno;
LOG( LERR, "TCP Process create failed. [%d][%s]", errorNum, strerror(errorNum) );
}
else if( processId == 0 ) // Child Process => Worker Process
{
// Worker Process Main 함수 호출 및 종료처리.
int n = EXIT_FAILURE;
CServiceFactory f;
CService * p = f.CreateSerivce(SERVICE_TYPE::TCP_SERVICE);
if(p)
{
n = WorkerMain( isDaemon, p );
delete p;
}
exit( n );
}
else // Parent Process => Logging
{
LOG( LINF, "TCP Process create success. PID[%d]" , processId);
// 잠시 대기
usleep(100000);
}
}
/// fail log monitor
static void MakeFailMon( bool isDaemon )
{
pid_t processId;
// Worker 프로세스 fork
processId = fork();
if( processId < 0 ) // Fork fail
{
int errorNum = errno;
LOG( LERR, "FailMon Process create failed. [%d][%s]", errorNum, strerror(errorNum) );
}
else if( processId == 0 ) // Child Process => Worker Process
{
// Worker Process Main 함수 호출 및 종료처리.
int n = EXIT_FAILURE;
CServiceFactory f;
CService * p = f.CreateSerivce(SERVICE_TYPE::FAIL_MON);
if(p)
{
n = WorkerMain( isDaemon, p );
delete p;
}
exit( n );
}
else // Parent Process => Logging
{
_FailMonPid = processId;
LOG( LINF, "FailMon Process create success. PID[%d]" , processId);
// 잠시 대기
usleep(100000);
}
}
/// @brief Worker Process 재생성(fork) 처리 함수
/// @return 생성 성공시 true, 실패시에는 false 를 반환.
bool ReMakeProcessWorker( bool isDaemon, int killpid )
{
if(killpid == _FailMonPid)
MakeFailMon(isDaemon);
else
MakeTCPProcess(isDaemon);
return true;
}
/// @brief Worker Process 생성 처리 함수
/// @return 생성 성공시 true, 실패시에는 false 를 반환.
bool MakeProcessWorker( bool isDaemon )
{
_MainPid = getpid();
// fail log monitor
MakeFailMon(isDaemon);
// TCP Process
CTCPService::SetPort(CMyConfig::GetInstance()->GetTCPListenPort());
if( CTCPService::MakeListenSocket() == false)
return false;
// Conf 에 정의된 Worker Process Count 만큼 Worker 프로세스 생성 처리.
for( int index = 0; index < CMyConfig::GetInstance()->GetWorkProcessCnt(); index++ )
{
MakeTCPProcess(isDaemon);
}
return true;
}
+36
View File
@@ -0,0 +1,36 @@
/***************************************************************************
cc_statd Worker Header ( Worker.h )
-----------------------------------------
begin : 2013/05/30
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/30 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __WORKER_PROCESS_H__
#define __WORKER_PROCESS_H__
#ifdef __cplusplus
extern "C" {
#endif
/// @brief Worker Process 재생성(fork) 처리 함수
/// @return 생성 성공시 true, 실패시에는 false 를 반환.
bool ReMakeProcessWorker( bool isDaemon, int killpid );
/// @brief Worker Process 생성(fork) 처리 함수
/// @return 생성 성공시 true, 실패시에는 false 를 반환.
bool MakeProcessWorker( bool isDaemon );
#ifdef __cplusplus
}
#endif
#endif /* __WORKER_PROCESS_H__ */
+68
View File
@@ -0,0 +1,68 @@
/***************************************************************************
CC Stat Daemon Global Setting ( cc_statd.h )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2011 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#ifndef __CC_STATD_H__
#define __CC_STATD_H__
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <exception>
// SOCI
#include <soci.h>
#include <soci-config.h>
#include <postgresql/soci-postgresql.h>
// XML
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <libxml++/libxml++.h>
using namespace std;
using namespace soci;
using namespace xmlpp;
#define LOGACONSOLE(level, msg) \
if(level >= LDBG) {\
_LOG( level, "%s", msg.str().c_str());\
cout << msg.str() << endl; msg.str("");}\
else {\
LOG( level, "%s", msg.str().c_str());\
cerr << msg.str() << endl; msg.str("");}\
msg.str("");
#endif // __CC_STATD_H__
+267
View File
@@ -0,0 +1,267 @@
/****************************************************************************
cc_statd Main ( main.cpp )
-----------------------------------------
begin : 2013/05/28
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/05/28 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
*****************************************************************************/
#include "cc_statd.h"
#include "ArgParser.h"
#include "Configs.h"
#include "Signals.h"
#include "Worker.h"
#include "Logger.h"
static bool _isExit = false;
static bool _isDaemon = true;
// print Version
static void Version()
{
cerr << "Version: " PROG_NAME " " PROG_VERSION << endl;
}
// print usage
static void Usage()
{
cerr << "Usage: " << PROG_NAME " [-c file]" << endl;
cerr << " [-v] [-h] [-D]" << endl;
cerr << "Options: " << endl;
cerr << " -v : show version number" << endl;
cerr << " -h : list available command line options (this page)" << endl;
cerr << " -D : run console mode" << endl;
cerr << " -c file : process directive reading config file" << endl;
cerr << endl << endl;
cerr << PROG_NAME <<" is a daemon to be stored in the CCDB the statistics of RC." << endl;
}
// signal function
static void SigTermMain( int nSignalNumber )
{
if(_isExit) return;
_isExit = true;
ostringstream msg;
// Signal Number 에 따른 로깅처리.
if( nSignalNumber == SIGTERM )
{
msg << "Main Process [" << getpid() << "] exit job start by user signal [SIGTERM]";
}
else
{
msg << "Main Process [" << getpid() << "] exit job start by user signal ["<< nSignalNumber <<"]";
}
cout << msg.str() << endl;
_LOG(LWAR, msg.str().c_str());
// KILL - Child
kill(0, SIGTERM);
// waitpid
while(waitpid(-1, NULL, WNOHANG) > 0);
}
static void SigChldMain( int nSignalNumber )
{
pid_t killPid;
int nKillStatus;
if(_isExit)
return;
while( ( killPid = waitpid( -1, &nKillStatus, WNOHANG ) ) > 0 )
{
if(WIFEXITED(nKillStatus))
{
// 자식 프로세스가 정상적으로 종료되었는지 검사.
LOG( LWAR, "Worker process[%d] killed by signal[SIGTERM]", killPid);
}
else if( WIFSIGNALED( nKillStatus ) )
{
// 자식 프로세스가 Signal 에 의해 종료되었는지 검사.
LOG( LWAR, "Worker process[%d] killed by signal[%d]", killPid, WTERMSIG( nKillStatus ) );
}
else
{
LOG( LWAR, "Worker process[%d] killed. Not signal", killPid );
}
// Worker Process 재생성 처리.
if( ReMakeProcessWorker(_isDaemon, killPid) == false )
{
// Worker Process 재성성 실패시 => 그냥 로깅
LOG( LERR, "Worker process recreate failed.");
}
else
{
LOG( LWAR, "Worker process recreate success by SIGCHLD");
}
}
// 오류 발생시 해당 내역 로깅
if( killPid < 0 )
{
LOG( LERR, "Main process error: SIG_CHLD receive but waitpid return error[%d][%s]", errno, strerror(errno));
}
}
// check running Process
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 strConfPath = DEFAULT_CONFIG_FILE;
// parse Input argument
CArgParser argparser(argc, argv);
if( argparser.checkvalue("-v") )
{
Version();
return EXIT_SUCCESS;
}
if( argparser.checkvalue("-h") )
{
Usage();
return EXIT_FAILURE;
}
if ( argparser.checkvalue("-D") )
{
_isDaemon = false;
}
string val;
if ( argparser.checkvalue("-c", &val) )
{
#ifdef _DEBUG
cout << "Change conf path " << strConfPath << " to " << val << endl;
#endif // _DEBUG
strConfPath = val;
}
if(!argparser.empty())
{
cerr<< "[error] can't understand argument." << endl;
Usage();
return EXIT_FAILURE;
}
// Check the program will duplicate
if( IsCurrentProcessRun() )
{
cerr << "[warning] Process [" << PROG_NAME << "] is already running...." << endl;
return EXIT_FAILURE;
}
//initialized Config object
if(CMyConfig::Init( PROG_NAME, strConfPath ) == false)
{
cerr << "[error] Failed to initialize the config object." << endl;
return EXIT_FAILURE;
}
// load config
if( CMyConfig::GetInstance()->LoadConf() == false )
{
cerr << "[error] Config load error." << CMyConfig::GetInstance()->GetErrMessage() << endl;
return EXIT_FAILURE;
}
if (CMyConfig::GetInstance()->CheckValue() == false)
{
cerr << "[error] Config load error." << CMyConfig::GetInstance()->GetErrMessage() << endl;
return EXIT_FAILURE;
}
// initialized Log object
if( CLogger::Init( PROG_NAME, CMyConfig::GetInstance()->GetAppLogRoot(),
CMyConfig::GetInstance()->GetAppLogLevel() ) == false )
{
cerr << "[error] Failed to initialize the log object." << endl;
return EXIT_FAILURE;
}
// set fail log path
string faillog = CLogger::GetInstance()->GetLogDir() + "/fail";
CMyConfig::GetInstance()->SetFailLogPath( faillog );
cout << PROG_NAME << (_isDaemon ? " Daemonize" : " Console Mode")
<< "......." << endl;
// daemonize
if(_isDaemon && daemon(1,0) == -1 )
{
cerr << "[error] Failed Daemonize.(errno : " << errno << ")" << endl;
return EXIT_FAILURE;
}
_LOG( LINF, "Main Process [%d] Starting...", getpid());
// set up signal handlers, now that we've daemonized/forked.
SetIgnoreSignal(_isDaemon);
SetSIGCHLD(SigChldMain);
SetSIGTERM(_isDaemon, SigTermMain);
// run work
if( MakeProcessWorker( _isDaemon ) == false )
{
_isExit = true;
}
// signal wait
while( _isExit == false )
{
pause();
}
// end
_LOG( LINF, "Main Process [%d] exit job end. Good Bye..", getpid());
CLogger::Exit();
CMyConfig::Exit();
cout << PROG_NAME << " End." << endl;
return EXIT_SUCCESS;
}