#include "stdafx.h" #include "AlarmFSM.h" #include "Event.h" AlarmFSM::AlarmFSM() : m_pConnection(NULL),m_b_alarmstate(FALSE) { InitializeCriticalSection(&cs); INIT_LIST_HEAD(&m_uploading_alarm); INIT_LIST_HEAD(&m_uploaded_alarm); m_iEachSend=0;//每次连接发送的数量 m_iRec=0;//累计收到的告警数目 m_iSend=0;//累计队列发送总数 m_iThrow=0;//累计队列丢弃总数 m_iFail=0;//累计发送失败总次数 m_iSucc=0;//累计发送成功总次数 } AlarmFSM::~AlarmFSM() { DeleteCriticalSection(&cs); } void AlarmFSM::OnStateTrans( int iSrcState, int iDstState ) { Dbg("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState)); } void AlarmFSM::OnSysVarEvent( const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName ) { } ErrorCodeEnum AlarmFSM::OnInit() { AddStateHooker(this); //...... CSmartPointer spFunction = m_pEntity->GetFunction(); CSmartPointer spConfig; ErrorCodeEnum Error = spFunction->OpenConfig(Config_CenterSetting, spConfig); if (Error_Succeed == Error) { Error = spConfig->ReadConfigValueInt("Alarm", "DealWarningTime", m_nDealWarningTime); if (Error_Succeed == Error) { Dbg("get DealWarningTime=%d from CenterSetting.ini", m_nDealWarningTime); } else { Dbg("get DealWarningTime from CenterSetting.ini failed"); } } if (m_nDealWarningTime == 0) { m_nDealWarningTime = 10; } return Error_Succeed; } ErrorCodeEnum AlarmFSM::OnExit() { return Error_Succeed; } void AlarmFSM::s0_on_entry() { //if (m_b_alarmstate) //{ // PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMSTATEUP)); //} //else if (!is_alarm_empty()) //{ // PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMUP)); //} //else //{ // ScheduleTimer(1, 5000); //} //connect if (!m_pConnection) { m_pConnection = new AlarmConnection(m_pEntity, this); if (m_pConnection->ConnectFromCentralSetting()&& m_pConnection->IsConnectionOK()) { //创建成功 }else{ //创建失败 Dbg("connect server fail,config or Servers Error!"); closeClientConn();//断开连接 } } if (!m_pConnection) { ScheduleTimer(1, 10000); // try 10 seconds later } else { PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMUP));//跳转S1状态 } } void AlarmFSM::s0_on_exit() { CancelTimer(1); } unsigned int AlarmFSM::s0_on_event( FSMEvent* event ) { //if (event->iEvt == EVT_TIMER) //{ // if (m_b_alarmstate) // { // PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMSTATEUP)); // } // else if (!is_alarm_empty()) // { // PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMUP)); // } // else // { // ScheduleTimer(1, 5000); // } //} if (event->iEvt == EVT_TIMER) { if (!m_pConnection) { m_pConnection = new AlarmConnection(m_pEntity, this); if (m_pConnection->ConnectFromCentralSetting()&& m_pConnection->IsConnectionOK()) { //创建成功 }else{ //创建失败 Dbg("connect server fail,config or Servers Error!"); closeClientConn();//断开连接 } } if (!m_pConnection) { ScheduleTimer(1, 10000); // try 10 seconds later } else { PostEventLIFO(new FSMEvent(USER_EVT_JMP_ALARMUP));//跳转S1状态 } } return 0; } void AlarmFSM::s1_on_entry() { //connect //if (!m_pConnection) //{ // m_pConnection = new AlarmConnection(m_pEntity, this); // if (!m_pConnection->ConnectFromCentralSetting()) // { // Dbg("connect server fail,config or Servers Error!"); // PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT)); // return; // } //} //if (m_pConnection->IsConnectionOK()) //upload //{ // EnterCriticalSection(&cs); // alarm_t*alarm = list_first_entry(&m_uploading_alarm,alarm_t,entry); // if (alarm == NULL) // { // Dbg("get alarm error"); // PostEventLIFO(new FSMEvent(USER_EVT_JMP_RELEASE)); // } // m_pConnection->SendAlarm(alarm); // //add by zl 20180306, 添加到历史告警列表 // add_UploadedAlarm(alarm); // list_del(&alarm->entry); // //delete alarm->Description; // //delete alarm->EntityName; // //delete alarm->SN; // //delete alarm; // //因使用malloc创建内存,用free释放 // free(alarm->Description); // alarm->Description=NULL; // free(alarm->EntityName); // alarm->EntityName=NULL; // free(alarm->SN); // alarm->SN=NULL; // delete alarm; // alarm=NULL; // Dbg("send alarm success"); // PostEventLIFO(new FSMEvent(USER_EVT_JMP_RELEASE)); // LeaveCriticalSection(&cs); //} //else //{ // //链接失效,需要先释放并清空链接,否一直不会重连 // m_pConnection->Close(); // m_pConnection->DecRefCount(); // m_pConnection = NULL; // PostEventLIFO(new FSMEvent(USER_EVT_JMP_RELEASE)); //} if(m_NewUploading_alarm.empty()){ PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//为空时,跳回S0状态 }else{ Dbg("send alarm statistic m_iRec=%d , m_iThrow=%d , UnSend=%d , m_iSend=%d , m_iSucc=%d , m_iFail=%d",m_iRec,m_iThrow,m_NewUploading_alarm.size(),m_iSend,m_iSucc,m_iFail); m_iEachSend = 0; //发送告警信息 if(SendAlarm()){ m_iEachSend++;//发送成功 }else{ PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT));//发送失败时,跳回S0状态 } } } void AlarmFSM::s1_on_exit() { CancelTimer(2); } unsigned int AlarmFSM::s1_on_event(FSMEvent* event) { //if (event->iEvt == USER_EVT_DISCONNECT) //{ // Dbg("rx disconnect evt at alarmupload s1"); // if (m_pConnection) // { // m_pConnection->Close(); // m_pConnection->DecRefCount(); // m_pConnection = NULL; // ScheduleTimer(2, 5000); // } //} //else if (event->iEvt == EVT_TIMER) //{ // if (!m_pConnection) // { // m_pConnection = new AlarmConnection(m_pEntity, this); // if (!m_pConnection->ConnectFromCentralSetting()) // { // Dbg("connect server fail,config or Servers Error!"); // PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT)); // } // } //} //else if (event->iEvt == EVT_TIMER) //{ // //继续发送 //} if (event->iEvt == USER_EVT_DISCONNECT_FAIL) { Dbg("disconnect 10s at alarmupload s1"); closeClientConn();//断开连接 ScheduleTimer(2, 10000); // try 10 seconds later } else if (event->iEvt == USER_EVT_DISCONNECT_SUCC) { Dbg("disconnect 3s at alarmupload s1"); closeClientConn();//断开连接 ScheduleTimer(2, 2000); // try 2 seconds later } else if (event->iEvt == EVT_TIMER) { PostEventLIFO(new FSMEvent(USER_EVT_JMP_START));//跳转S0状态 } else if (event->iEvt ==USER_EVT_UPLOAD_ANS) { if(m_iEachSend<=50) { if(!m_NewUploading_alarm.empty()){ if(SendAlarm()){ m_iEachSend++;//发送成功 }else{ PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//发送失败时,跳回S0状态 } }else{ PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//为空时,跳回S0状态 } } else { PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_SUCC));//达到一定发送数量,主动断开,跳回S0状态 } } return 0; } void AlarmFSM::s2_on_entry() { //connect if (!m_pConnection) { m_pConnection = new AlarmConnection(m_pEntity, this); if (!m_pConnection->ConnectFromCentralSetting()) { Dbg("connect server fail,config or Servers Error!"); } } if (m_pConnection->IsConnectionOK()) //upload alarm state { if (m_b_alarmstate) { m_pConnection->SendAlarmState(&m_uploading_alarmstate); Dbg("send alarmstate success"); delete m_uploading_alarmstate.Description; PostEventLIFO(new FSMEvent(USER_EVT_JMP_RELEASE)); } } else { //链接失效,需要先释放并清空链接,否则一直不会重连 m_pConnection->Close(); m_pConnection->DecRefCount(); m_pConnection = NULL; PostEventLIFO(new FSMEvent(USER_EVT_JMP_RELEASE)); } } void AlarmFSM::s2_on_exit() { m_b_alarmstate = FALSE; CancelTimer(3); } unsigned int AlarmFSM::s2_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_DISCONNECT) { Dbg("rx disconnect evt at alarm upload s2"); if (m_pConnection) { m_pConnection->Close(); m_pConnection->DecRefCount(); m_pConnection = NULL; } ScheduleTimer(3, 10000); } return 0; } void AlarmFSM::s3_on_entry() { //modify by zl 20180314,发送完,马上断开链接可能会导致服务端无法接受到请求,改用长链接 /*if (m_pConnection) { m_pConnection->Close(); m_pConnection->DecRefCount(); m_pConnection = NULL; LogEvent(Severity_Low,EVENT_MOD_ALARM_INITIATIVE_DISCONNECT,"Connecting Closed"); }*/ PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT)); if (!m_pConnection) { ScheduleTimer(4, 1000); // try 30 seconds later } } void AlarmFSM::s3_on_exit() { CancelTimer(4); } unsigned int AlarmFSM::s3_on_event(FSMEvent* event) { if (event->iEvt == USER_EVT_DISCONNECT) { Dbg(" disconnect evt at alarm upload s3"); /*if (m_pConnection) { m_pConnection->Close(); m_pConnection->DecRefCount(); m_pConnection = NULL; }*/ } return 0; } //增加告警 void AlarmFSM::add_alarm(alarm_t*alarm) { EnterCriticalSection(&cs); add_new_alarm(alarm,&m_uploading_alarm); LeaveCriticalSection(&cs); } //设置告警状态 void AlarmFSM::set_alarm_state(const CUUID nLogID,DWORD LifeId,const SeverityLevelEnum eLevel, DWORD Item,const char *pszMessage) { m_uploading_alarmstate.SN = nLogID; _itoa((int)eLevel,&m_uploading_alarmstate.Level,16); m_uploading_alarmstate.LifeID = LifeId; m_uploading_alarmstate.Item = Item; char cDescription[512]; strcpy(cDescription,pszMessage); m_uploading_alarmstate.Description = _strdup(cDescription); m_b_alarmstate = TRUE; } //获取告警数量 bool AlarmFSM::is_alarm_empty() { EnterCriticalSection(&cs); bool i = list_empty(&m_uploading_alarm); LeaveCriticalSection(&cs); return i; } bool AlarmFSM::is_UploadedAlarm_empty() { EnterCriticalSection(&cs); bool i = list_empty(&m_uploaded_alarm); LeaveCriticalSection(&cs); return i; } static time_t NowTime() { time_t t_Now = time(0); struct tm* tm_Now = localtime(&t_Now); /*tm_Now->tm_hour =0; tm_Now->tm_min = 0; tm_Now->tm_sec = 0;*/ return mktime(tm_Now); } void AlarmFSM::add_UploadedAlarm(alarm_t*alarm) { alarmUpgraded_t*upedAlarm = new alarmUpgraded_t(); upedAlarm->EntityName = new char[32]; if (NULL != upedAlarm->EntityName) { memset(upedAlarm->EntityName, 0, 32); } upedAlarm->SN = new char[20]; if (NULL != upedAlarm->SN) { memset(upedAlarm->SN, 0, 20); } upedAlarm->Description = new char[512]; if (NULL != upedAlarm->Description) { memset(upedAlarm->Description, 0, 512); } strcpy(upedAlarm->EntityName,alarm->EntityName); strcpy(upedAlarm->SN,alarm->SN); upedAlarm->LifeID = alarm->LifeID; upedAlarm->Item = alarm->Item; upedAlarm->UserCode = alarm->UserCode; upedAlarm->Level = alarm->Level; strcpy(upedAlarm->Description,alarm->Description); upedAlarm->time = NowTime(); //如果是相同实体且相同描述,则更新告警。否则做为新告警添加 if (!update_UploadedAlarm(upedAlarm)) { EnterCriticalSection(&cs); add_new_upalarm(upedAlarm,&m_uploaded_alarm); LeaveCriticalSection(&cs); } } bool AlarmFSM::find_UploadedAlarm(alarm_t*alarm) { EnterCriticalSection(&cs); if (is_UploadedAlarm_empty()) { return false; } //time_t tNow = NowTime(); //获取时间报错,改为直接获取 time_t t_Now = time(0); struct tm* tm_Now = localtime(&t_Now); time_t tNow = mktime(tm_Now); //Dbg("tNow[%d]", tNow); alarmUpgraded_t* uploadedAlarm; list_for_each_entry(uploadedAlarm, &m_uploaded_alarm, alarmUpgraded_t, entry) { if (0 == strcmp(uploadedAlarm->EntityName, alarm->EntityName) && 0 == strcmp(uploadedAlarm->Description, alarm->Description)) { if (tNow > uploadedAlarm->time) { UINT nSecond = tNow - uploadedAlarm->time; UINT nMin = nSecond/60; if (nMin <= m_nDealWarningTime) { //在指定时间内(可配置),收到同一实体的同一告警,去重 Dbg("find same uploaded alarm list, don't need to send again"); return true; } } else { Dbg("uploadedAlarm->time[%d] >= tNow[%d], time is wrong", uploadedAlarm->time, tNow); } } } LeaveCriticalSection(&cs); return false; } bool AlarmFSM::update_UploadedAlarm(alarmUpgraded_t*alarm) { EnterCriticalSection(&cs); if (is_UploadedAlarm_empty()) { return false; } alarmUpgraded_t* uploadedAlarm; list_for_each_entry(uploadedAlarm, &m_uploaded_alarm, alarmUpgraded_t, entry) { if (0 == strcmp(uploadedAlarm->EntityName, alarm->EntityName) || 0 == strcmp(uploadedAlarm->Description, alarm->Description)) { update_upalarm(alarm, uploadedAlarm); //替换后,旧的对象需要清理 //free(uploadedAlarm->Description); //free(uploadedAlarm->EntityName); //free(uploadedAlarm->SN); delete[] uploadedAlarm->Description; uploadedAlarm->Description=NULL; delete[] uploadedAlarm->EntityName; uploadedAlarm->EntityName=NULL; delete[] uploadedAlarm->SN; uploadedAlarm->SN=NULL; delete uploadedAlarm; uploadedAlarm=NULL; return true; } } LeaveCriticalSection(&cs); return false; } //增加消息到新告警列表 void AlarmFSM::add_NewAlarm(alarm_t* alarm) { EnterCriticalSection(&cs); if(m_NewUploading_alarm.size()>=UPLOG_MAX_COUNT){ //Dbg("队列已满,删除首元素"); m_iThrow++; alarm_t* oldAlarm = (alarm_t*)(*m_NewUploading_alarm.begin());//集合首个元素 m_NewUploading_alarm.erase(m_NewUploading_alarm.begin());//集合删除首元素 free(oldAlarm->Description); oldAlarm->Description=NULL; free(oldAlarm->EntityName); oldAlarm->EntityName=NULL; free(oldAlarm->SN); oldAlarm->SN=NULL; delete oldAlarm; oldAlarm=NULL; } m_NewUploading_alarm.push_back(alarm);//加入队列 LeaveCriticalSection(&cs); } //取出消息从新告警列表 alarm_t* AlarmFSM::removeAlarm() {//加锁,取出先进的队列日志,注意释放内存空间 alarm_t* dAlarm = NULL; EnterCriticalSection(&cs); if(m_NewUploading_alarm.empty()){ //return NULL; }else{ dAlarm = (alarm_t*)(*m_NewUploading_alarm.begin());//集合首个元素 m_NewUploading_alarm.erase(m_NewUploading_alarm.begin());//集合删除首元素 } LeaveCriticalSection(&cs); return dAlarm;//返回 } //关闭连接 void AlarmFSM::closeClientConn() { if(m_pConnection!=NULL){ m_pConnection->Close(); m_pConnection->DecRefCount(); m_pConnection = NULL; } } //发送新告警信息 bool AlarmFSM::SendAlarm(){ alarm_t*alarm = removeAlarm(); if (alarm == NULL) { Dbg("get alarm error"); return false; } m_iSend++;//发送计数 m_pConnection->SendAlarm(alarm); free(alarm->Description); alarm->Description=NULL; free(alarm->EntityName); alarm->EntityName=NULL; free(alarm->SN); alarm->SN=NULL; delete alarm; alarm=NULL; return true; }