#include #include #include #include #include #include #include #include #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; iversion.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; iActP() ){ 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; iiClientType, 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."); }