Initial commit
This commit is contained in:
@@ -0,0 +1,566 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "ServiceThread.h"
|
||||
#include "DBInterface.h"
|
||||
#include "MessageThread.h"
|
||||
#include "DataBuffers.h"
|
||||
#include "ResponseManager.h"
|
||||
#include "EpollThread.h"
|
||||
#include "INIParser.h"
|
||||
|
||||
extern int g_eDebug;
|
||||
extern int g_iChkStyle;
|
||||
extern MHTHREADLIST g_lstMessageHandleThreads;
|
||||
extern CSema* g_pSemaStop;
|
||||
|
||||
int g_iSignal = 0;
|
||||
CSema* g_pSemaService = NULL;
|
||||
CSema* g_pSemaClientCheck = NULL;
|
||||
CSema* g_pSemaTimer = NULL;
|
||||
|
||||
CUDPMessageReceiveThread * g_pMessageReceiveThread = NULL;
|
||||
EpollThread* g_pEpollThread = NULL;
|
||||
CDataBufferManager* g_pDataBuffers = NULL;
|
||||
CResponseManager* g_pResponses = NULL;
|
||||
int g_aStyleRecomList[MAX_STYLE_NUM+1];
|
||||
TQNAITEM g_lstCommonQnA[200];
|
||||
TNOTICEITEM g_lstPublicNotice[MAX_NOTICE_NUM];
|
||||
int g_nCommonQnANum = 0, g_nPublicNoticeNum = 0;
|
||||
|
||||
TCLIENTVERSION* g_pVersionClient = NULL;
|
||||
TTESTVERSION* g_pVersionClientTest = NULL;
|
||||
|
||||
int g_nClientTypeNum = 0,
|
||||
g_nClientTestNum = 0;
|
||||
HANDLE g_hEvClientCheck = NULL;
|
||||
char g_strStyleFileDir[256] = "";
|
||||
char g_strWebFileDir[256] = "";
|
||||
char g_strMusicFileDir[256] = "";
|
||||
char g_strMusicLocation[8] = "";
|
||||
char g_strServiceDir[256] = "";
|
||||
|
||||
void SignalHandler(int signo)
|
||||
{
|
||||
if(signo==SIGTERM || signo==SIGINT || signo==SIGUSR1){
|
||||
DebugPrint("Terminate by signal: %d", signo);
|
||||
|
||||
if(signo==SIGUSR1)
|
||||
g_iSignal = signo;
|
||||
|
||||
if(g_pSemaStop)
|
||||
g_pSemaStop->ActV();
|
||||
}
|
||||
else if(signo==SIGALRM){
|
||||
if(g_pSemaTimer)
|
||||
g_pSemaTimer->ActV();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateLog()
|
||||
{
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
|
||||
char szBufPath[256] = "";
|
||||
|
||||
sprintf( szBufPath, "%s/log/", g_strServiceDir );
|
||||
|
||||
// DebugPrint(szBufPath);
|
||||
|
||||
if( chdir(szBufPath) == -1)
|
||||
mkdir(szBufPath, S_IRWXU|S_IRWXG);
|
||||
|
||||
sprintf( szBufPath, "%s%04d-%02d-%02d.log", szBufPath, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
|
||||
|
||||
DebugModuleClose();
|
||||
|
||||
int iDebug = g_eDebug>0 ? g_eDebug : 1;
|
||||
|
||||
DebugModuleInitialize( 0xFFFF, (EDPrintDest)iDebug, szBufPath );
|
||||
}
|
||||
|
||||
#define INI_FILE_NAME "DBService.ini"
|
||||
#define STR_TESTVERSION_SECTION "TEST_VERSIONS"
|
||||
#define STR_TESTVERSION "VERSIONS_STRING"
|
||||
#ifdef _WIN32
|
||||
#define stat _stat
|
||||
#endif
|
||||
|
||||
time_t g_ftIniModify = 0;
|
||||
void ReadConfigParams()
|
||||
{
|
||||
char szFileName[260] = "";
|
||||
sprintf( szFileName, "%s/%s", g_strServiceDir, INI_FILE_NAME );
|
||||
|
||||
struct stat stFile;
|
||||
if( stat( szFileName, &stFile )!=0 ){
|
||||
DebugPrint( "get ini file stat error: %d", errno );
|
||||
return;
|
||||
}
|
||||
|
||||
if( g_ftIniModify!=stFile.st_mtime ){
|
||||
if(g_pSemaClientCheck->ActP())
|
||||
return;
|
||||
|
||||
//printf( "retrive config.\n" );
|
||||
TTESTVERSION aVersion[10];
|
||||
int num = 0;
|
||||
|
||||
INIParser parser;
|
||||
parser.ReadINI(szFileName);
|
||||
|
||||
string szLine = parser.GetValue(STR_TESTVERSION_SECTION, STR_TESTVERSION);
|
||||
if( !szLine.empty() ){
|
||||
char szBuf[512] = "";
|
||||
strcpy(szBuf, szLine.c_str());
|
||||
|
||||
char *tokenPtr=strtok( szBuf, "|" );
|
||||
for( ; tokenPtr!=NULL; num++ ){
|
||||
int iInner, iMaj, iMin, iMod, iBuil;
|
||||
sscanf( tokenPtr, "%d,%d.%d.%d", &iInner, &iMaj, &iMin, &iMod );//, &iBuil );
|
||||
|
||||
aVersion[num].iClientType = iInner;
|
||||
aVersion[num].version.majorVersion = iMaj;
|
||||
aVersion[num].version.minorVersion = iMin;
|
||||
aVersion[num].version.modifyVersion = iMod;
|
||||
// aVersion[num].version.buildVersion = iBuil;
|
||||
|
||||
tokenPtr = strtok( NULL, "|" );
|
||||
}
|
||||
}
|
||||
|
||||
parser.Clear();
|
||||
|
||||
if( g_nClientTestNum>0 && g_nClientTestNum!=num ){
|
||||
delete[] g_pVersionClientTest;
|
||||
g_pVersionClientTest = NULL;
|
||||
}
|
||||
|
||||
g_nClientTestNum = num;
|
||||
|
||||
if( num>0 ){
|
||||
if( !g_pVersionClientTest ){
|
||||
g_pVersionClientTest = new TTESTVERSION[num];
|
||||
}
|
||||
|
||||
for( int i=0; i<num; i++ ){
|
||||
TTESTVERSION* pVersion = &(g_pVersionClientTest[i]);
|
||||
memcpy( pVersion, &aVersion[i], sizeof(TTESTVERSION) );
|
||||
|
||||
DebugPrint( "测试版本: %d.%d.%d\t软件内部编号: %d",
|
||||
pVersion->version.majorVersion, pVersion->version.minorVersion,
|
||||
pVersion->version.modifyVersion, //pVersion->version.buildVersion, //不设置构建版本
|
||||
pVersion->iClientType );
|
||||
}
|
||||
}
|
||||
else{
|
||||
DebugPrint( "No test version." );
|
||||
}
|
||||
|
||||
g_pSemaClientCheck->ActV();
|
||||
// SetEvent( g_hEvClientCheck );
|
||||
|
||||
g_ftIniModify = stFile.st_mtime;
|
||||
}
|
||||
else{
|
||||
DebugPrint( "No config update." );
|
||||
}
|
||||
}
|
||||
|
||||
void GetStyleRecomList()
|
||||
{
|
||||
int tempList[MAX_STYLE_NUM+1];
|
||||
memset( tempList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
|
||||
int num = MAX_STYLE_NUM;
|
||||
int ret = f_DB_GetRecomStyleIDs( &num, tempList );
|
||||
|
||||
if( ret==0 ){
|
||||
tempList[MAX_STYLE_NUM] = num;
|
||||
memcpy( g_aStyleRecomList, tempList, sizeof(int)*(MAX_STYLE_NUM+1) );
|
||||
|
||||
DebugPrint( "Recommand style num : %d", num );
|
||||
}
|
||||
else{
|
||||
DebugPrint( "DB_GetRecomStyleIDs return %d", ret );
|
||||
}
|
||||
}
|
||||
|
||||
void GetCommonQnAList()
|
||||
{
|
||||
// int dtUpdate = 0;
|
||||
// for( int i=0; i<g_nCommonQnANum; i++ ){
|
||||
// if( dtUpdate<g_lstCommonQnA[i].dtUpdate ){
|
||||
// dtUpdate = g_lstCommonQnA[i].dtUpdate;
|
||||
// }
|
||||
// }
|
||||
|
||||
// g_nCommonQnANum = f_DB_GetCommonQnA( dtUpdate, g_nCommonQnANum, g_lstCommonQnA );
|
||||
g_nCommonQnANum = f_DB_GetCommonQnA( 0, g_nCommonQnANum, g_lstCommonQnA );
|
||||
|
||||
DebugPrint( "Common QnA num : %d", g_nCommonQnANum );
|
||||
}
|
||||
|
||||
void GetPublicNoticeList()
|
||||
{
|
||||
g_nPublicNoticeNum = f_DB_GetNotice( MAX_NOTICE_NUM, g_lstPublicNotice, 0 );
|
||||
|
||||
DebugPrint( "Public notice num : %d", g_nPublicNoticeNum );
|
||||
}
|
||||
|
||||
void GetClientUpdateVersion()
|
||||
{
|
||||
if( !g_pSemaClientCheck || g_pSemaClientCheck->ActP() ){
|
||||
return;
|
||||
}
|
||||
|
||||
int nOldTypeNum = g_nClientTypeNum;
|
||||
g_nClientTypeNum = f_DB_GetClientTypeNumber();
|
||||
|
||||
TCLIENTVERSION * pClients = NULL;
|
||||
if( g_nClientTypeNum>0 ){ //有可用客户端
|
||||
pClients = new TCLIENTVERSION[g_nClientTypeNum];
|
||||
if( f_DB_GetClientVersion( pClients, g_nClientTypeNum )<0 ){ //获取客户端信息
|
||||
delete[] pClients;
|
||||
pClients = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool bChange = true;
|
||||
if( g_nClientTypeNum<0 ){
|
||||
DebugPrint( "获取最新客户端类型数失败!" );
|
||||
g_nClientTypeNum = nOldTypeNum; //不改变原客户端信息
|
||||
bChange = false;
|
||||
}
|
||||
else if(g_nClientTypeNum>0 && !pClients){
|
||||
DebugPrint( "获取最新客户端版本信息失败!" );
|
||||
g_nClientTypeNum = nOldTypeNum; //不改变原客户端信息
|
||||
bChange = false;
|
||||
}
|
||||
else if( g_nClientTypeNum==nOldTypeNum ){ //数量相同则比较是否有改变
|
||||
bChange = false;
|
||||
for( int i=0; i<g_nClientTypeNum; i++ ){
|
||||
TCLIENTVERSION* pOldVersion = &(g_pVersionClient[i]);
|
||||
TCLIENTVERSION* pNewVersion = &(pClients[i]);
|
||||
if(memcmp(pOldVersion, pNewVersion, sizeof(TCLIENTVERSION))){
|
||||
bChange = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bChange){ //有变化
|
||||
if(g_pVersionClient) //清理原内存
|
||||
delete[] g_pVersionClient;
|
||||
|
||||
g_pVersionClient = pClients;
|
||||
|
||||
for( int i=0; i<g_nClientTypeNum; i++ ){ //打印信息
|
||||
TCLIENTVERSION* pVersion = &(g_pVersionClient[i]);
|
||||
|
||||
DebugPrint( "软件内部编号: %d\n\t最新客户端版本: %d.%d.%d.%04d\n\t发布时间: %d-%d-%d",
|
||||
pVersion->iClientType,
|
||||
pVersion->swInfo.version.majorVersion, pVersion->swInfo.version.minorVersion,
|
||||
pVersion->swInfo.version.modifyVersion, pVersion->swInfo.version.buildVersion,
|
||||
pVersion->swInfo.tIssueDate>>16, (pVersion->swInfo.tIssueDate&0xFF00)>>8, (pVersion->swInfo.tIssueDate&0xFF));
|
||||
|
||||
}
|
||||
}
|
||||
else if(pClients){ //无变化清理内存
|
||||
delete[] pClients;
|
||||
pClients = NULL;
|
||||
}
|
||||
|
||||
g_pSemaClientCheck->ActV();
|
||||
}
|
||||
|
||||
bool ServiceInit()
|
||||
{
|
||||
g_pSemaService = new CSema(NULL, 0);
|
||||
g_pSemaClientCheck = new CSema(NULL, 1);
|
||||
g_pSemaTimer = new CSema(NULL, 0);
|
||||
|
||||
CreateLog();
|
||||
//DebugPrint("DebugModuleInitialize success!\n");
|
||||
|
||||
//载入数据库访问模块
|
||||
if( !LoadDB() ){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
f_DB_GetPath( g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
|
||||
DebugPrint( "Style_dir: %s\n\tWeb_dir: %s\n\tMusic_dir: %s", g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
|
||||
if( strlen(g_strMusicFileDir)>0 ){
|
||||
char* pos = strstr( g_strMusicFileDir, "File" )+4;
|
||||
if( pos[0]!='/' && pos[0]!='\\' ){
|
||||
int num;
|
||||
sscanf( pos, "%d", &num );
|
||||
sprintf( g_strMusicLocation, "%d", num );
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
//修改风格信息专用
|
||||
if( g_iChkStyle>0 ){
|
||||
// UpdateStyleInfo();
|
||||
// ModifyStyleDesc();
|
||||
return FALSE;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
GetClientUpdateVersion();
|
||||
memset( g_aStyleRecomList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
|
||||
GetStyleRecomList();
|
||||
|
||||
ReadConfigParams();
|
||||
|
||||
GetCommonQnAList();
|
||||
GetPublicNoticeList();
|
||||
|
||||
//创建数据接收
|
||||
g_pDataBuffers = new CDataBufferManager;
|
||||
//创建消息响应管理
|
||||
g_pResponses = new CResponseManager;
|
||||
|
||||
//生成UDP消息接收线程
|
||||
CUDPSocket * pSocket = new CUDPSocket( LISTEN_PORT );
|
||||
if( pSocket && pSocket->IsOpen() ){
|
||||
g_pMessageReceiveThread = new CUDPMessageReceiveThread( 3000, pSocket );
|
||||
g_pMessageReceiveThread->Resume();
|
||||
|
||||
//生成消息处理线程池
|
||||
for( int i=0; i<20; i++ ){
|
||||
CMessageHandleThread* pThread = new CMessageHandleThread( 3000, pSocket );
|
||||
g_lstMessageHandleThreads.push_back( pThread );
|
||||
}
|
||||
}
|
||||
|
||||
//生成epoll线程
|
||||
g_pEpollThread = new EpollThread();
|
||||
g_pEpollThread->Resume();
|
||||
|
||||
printf("Composer Service is running...\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServiceDeInit()
|
||||
{
|
||||
printf("Composer Service is stopping...\n");
|
||||
|
||||
// if( g_hEvClientCheck ){
|
||||
// CloseHandle( g_hEvClientCheck );
|
||||
// }
|
||||
if( g_pSemaClientCheck ){
|
||||
delete g_pSemaClientCheck;
|
||||
g_pSemaClientCheck = NULL;
|
||||
}
|
||||
|
||||
if( g_pSemaTimer ){
|
||||
delete g_pSemaTimer;
|
||||
g_pSemaTimer = NULL;
|
||||
}
|
||||
|
||||
if( g_pVersionClient ){
|
||||
delete[] g_pVersionClient;
|
||||
g_pVersionClient = NULL;
|
||||
}
|
||||
|
||||
if( g_pMessageReceiveThread ){
|
||||
g_pMessageReceiveThread->Terminate();
|
||||
delete g_pMessageReceiveThread;
|
||||
g_pMessageReceiveThread = NULL;
|
||||
}
|
||||
|
||||
MHTHREADLIST::iterator iMT = g_lstMessageHandleThreads.begin();
|
||||
while( iMT!=g_lstMessageHandleThreads.end() ){
|
||||
(*iMT)->Terminate();
|
||||
// (*iMT)->Resume();
|
||||
delete (*iMT);
|
||||
|
||||
iMT = g_lstMessageHandleThreads.erase( iMT );
|
||||
}
|
||||
|
||||
if( g_pEpollThread ){
|
||||
g_pEpollThread->Terminate();
|
||||
}
|
||||
|
||||
FreeDB();
|
||||
|
||||
if( g_pDataBuffers ){
|
||||
delete g_pDataBuffers;
|
||||
g_pDataBuffers = NULL;
|
||||
}
|
||||
|
||||
if( g_pResponses ){
|
||||
delete g_pResponses;
|
||||
g_pResponses = NULL;
|
||||
}
|
||||
|
||||
if( g_pEpollThread ){
|
||||
delete g_pEpollThread;
|
||||
g_pEpollThread = NULL;
|
||||
}
|
||||
|
||||
DebugModuleClose();
|
||||
|
||||
printf( "System unloaded!\n" );
|
||||
|
||||
if(g_pSemaService)
|
||||
g_pSemaService->ActV();
|
||||
|
||||
printf("Composer Service stopped.\n");
|
||||
}
|
||||
|
||||
// void CheckProCount()
|
||||
// {
|
||||
// //////////////////////////////////////////////////////
|
||||
// // 统计 PC pro 函数
|
||||
// #include "MessageHandle.h"
|
||||
// int n826(0), nOth(0);
|
||||
// GetProCount(n826, nOth);
|
||||
|
||||
// DebugPrint("PC pro使用人数 826 : other = %d : %d", n826, nOth);
|
||||
// //////////////////////////////////////////////////////
|
||||
// }
|
||||
|
||||
void* OneDaySchedule(void* arg)
|
||||
{
|
||||
// CheckProCount();
|
||||
|
||||
CreateLog();
|
||||
GetStyleRecomList();
|
||||
GetCommonQnAList();
|
||||
CheckMemoryUsage();
|
||||
|
||||
DebugPrint( "OneDaySchedule exit." );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SetTimer(int sec)
|
||||
{
|
||||
itimerval value;
|
||||
value.it_value.tv_sec = sec;
|
||||
value.it_value.tv_usec = 0;
|
||||
value.it_interval = value.it_value;
|
||||
|
||||
return setitimer(ITIMER_REAL, &value, NULL);
|
||||
}
|
||||
|
||||
int GetTimeCount()
|
||||
{
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
|
||||
return tm->tm_hour * 60 * 60 + tm->tm_min * 60 + tm->tm_sec;
|
||||
}
|
||||
|
||||
CServiceThread::CServiceThread():CThread(3000)
|
||||
{
|
||||
// getcwd(g_strServiceDir, 256);
|
||||
if(readlink("/proc/self/exe", g_strServiceDir, 256)>0){
|
||||
char* p = strrchr(g_strServiceDir,'/');
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CServiceThread::Terminate()
|
||||
{
|
||||
CThread::Terminate();
|
||||
|
||||
if( g_pSemaTimer )
|
||||
g_pSemaTimer->ActV();
|
||||
}
|
||||
|
||||
void CServiceThread::Main()
|
||||
{
|
||||
DWORD timeCount = 0;
|
||||
|
||||
if( ServiceInit() ){
|
||||
timeCount = GetTimeCount();
|
||||
|
||||
/* 设置信号的处理方式 */
|
||||
signal(SIGALRM, SignalHandler);
|
||||
signal(SIGTERM, SignalHandler);
|
||||
signal(SIGINT, SignalHandler);
|
||||
signal(SIGUSR1, SignalHandler);
|
||||
|
||||
/* 以系统真实的时间来计算,将送出SIGALRM信号 */
|
||||
if (SetTimer(1) < 0){
|
||||
/* 函数调用返回错误 */
|
||||
DebugPrint("Setitimer Failed : %s", strerror(errno));
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
while(!m_bExit){
|
||||
g_pSemaTimer->ActP();
|
||||
|
||||
// if( g_pIOCmpltThread ){
|
||||
// g_pIOCmpltThread->OnTimer();
|
||||
// }
|
||||
|
||||
if( g_pDataBuffers ){
|
||||
g_pDataBuffers->OnTimer();
|
||||
}
|
||||
|
||||
if( g_pResponses ){
|
||||
g_pResponses->OnTimer();
|
||||
}
|
||||
|
||||
if( ++timeCount>=86400 ){ //00:00:00
|
||||
// if( ++timeCount>=15 ){ //test 10 minutes
|
||||
// timeCount = 0; //test
|
||||
timeCount = GetTimeCount();
|
||||
|
||||
if( timeCount<3600 ){
|
||||
#ifdef _WIN32
|
||||
CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)OnTimerFunc, 0, 0, 0 );
|
||||
#else
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init (&attr);
|
||||
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create( &tid, &attr, OneDaySchedule, NULL);
|
||||
pthread_attr_destroy (&attr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ( timeCount & 0x1FF )==0 ){ //0x1FF 512s~9m 定时清除VIP登录记录(10分钟内最多3个设备同时登录)
|
||||
f_DB_CleanVipLog();
|
||||
}
|
||||
|
||||
if( timeCount>0 && ( timeCount & 0xFFF )==0 //0xFFF 4095s~68m~1h 获取测试版本信息等
|
||||
&& timeCount < 86000 ){ //23:53:35秒的检测跳过
|
||||
ReadConfigParams();
|
||||
GetClientUpdateVersion();
|
||||
GetPublicNoticeList();
|
||||
}
|
||||
|
||||
// if( ( timeCount & 0x1FFF )==0 ){ //0x1FFF 8191s~136m~2h 获取发布版本信息
|
||||
// GetClientUpdateVersion();
|
||||
// GetPublicNoticeList();
|
||||
// }
|
||||
}
|
||||
|
||||
SetTimer(0);
|
||||
|
||||
// CheckProCount();
|
||||
|
||||
ServiceDeInit();
|
||||
|
||||
DebugPrint("Service main thread exited.");
|
||||
}
|
||||
Reference in New Issue
Block a user