⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 systemexit.cpp

📁 SMS gateway. SMS protocol for CHINA mobile, unicom, lingtong. Using mysql to exchange message.
💻 CPP
字号:
/**********************************************************************
  FileName            : SystemExit.cpp
  Description         : 网关系统安全退出模块
  Version             : 1.0
  Date                : 2003年10月27日
  Author              : 刘荣辉
  Other               : 
***********************************************************************/

#include "GateWay.h"

//===============网关系统退出信号处理函数===================
void CGateWay::ExitSig(int sig)
{
	printf("\n Notice: Got Signal[%d] = [%s].\n",sig,strsignal(sig));
	CGateWay::ToExit = 1;
	return;
}

void CGateWay::SetTSD(int signo)	//线程TSD置1
{
	 //printf("\n SetTSD========== \n");
	 *(int*)pthread_getspecific(ThreadKey)=1;
	 return;
}
//===================网关系统安全退出模块===================
void CGateWay::SafeExit()
{
	int RetCode;
	char FileName[80];	//备份文件路径名
	int PackType,RecvNum,SendNum;
	int RecvBak,SendBak;
	RecvQUnit RUnit;
	SendQUnit SUnit;
	char sSysEvent[SYS_EVENT_LEN];	//记录系统事件的字符串
	FileOpr *Qbackup = new FileOpr();	//用于将队列单元备份到文件的操作对象

	strcpy(sSysEvent,"LOG: Got Terminate Signal,System is preparing to exit....");
	WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);   //写系统日志

	//退出网关控制台线程
	if(ConsoleThr)
		pthread_kill(ConsoleThr, SIGUSR1);
	//退出MO、MT短消息分发线程
	if(MTForwordThr)
		pthread_kill(MTForwordThr, SIGUSR1);
	if(MOForwordThr)
		pthread_kill(MOForwordThr, SIGUSR1);
	//退出下端连接监听线程
	if(DnListenThr)
		pthread_kill(DnListenThr, SIGUSR1);

	int AliveUpNode=0;	//在线上节点数
	int AliveDnNode;	//在线下节点数
	for(int i=0;i<UPNODE_NUM; i++)	//检查在线上节点数
	{
		UpNode[i].ToExit=1;	//置退出标识
		if(UpNode[i].State==0)
			AliveUpNode++;
		if(UpNode[i].WriteThr)
			pthread_kill(UpNode[i].WriteThr, SIGUSR1);	//退出所有上节点发送线程
	}
	Map_Pos Pos;
    CDnNode *theDnNode;
	Sock_CP_Map.PosInit(&Pos);
	while(1)
	{
		RetCode = Sock_CP_Map.GetNext((char **)&theDnNode, &Pos);
		if(theDnNode==NULL || RetCode<0)	//读到的是最后一个元素或者早已为空,下次将从头开始取
			break;
		theDnNode->ToExit=1;	//置退出标识
		if(theDnNode->SendThr)
			pthread_kill(theDnNode->SendThr, SIGUSR1);	//退出所有下节点的发送线程
	}

	//================轮流检查各在线节点,找适当时机断开连接================
	while(1)
	{
		if(AliveUpNode)
		{
			for(int i=0;i<UPNODE_NUM; i++)	//检查一遍所有在线上节点
			{
				//检查各节点的已发送队列是否为空
				if(UpNode[i].SentQ.IsEmpty())
				{
					UpNode[i].SendLogout();  //直接发送Logout包
					/*是否需要?
					RetCode = shutdown(UpNode[i].TcpSock.sock, SHUT_RDWR);	//关闭连接,对应收发线程将退出
					if(RetCode)
					{
						sprintf(sSysEvent,"Error: Failed to shutdown the socket of UpNode[%d]!",UpNode[i].NodeID);
						WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);   //写系统日志
					}*/
					AliveUpNode--;
					#ifdef DEBUG
					printf("\n SafeExit: Connection[%d] to UpNode[%d] is cut!RetCode=[%d].\n",UpNode[i].TcpSock.sock,UpNode[i].NodeID,RetCode);
					#endif
				}
			}
		}//if(AliveUpNode)
		AliveDnNode = Sock_CP_Map.GetSize();	//在线下节点数
		if(AliveDnNode)
		{
			for(;;)	//检查一遍所有在线下节点
			{
				//获取下一个下节点的指针
				theDnNode=NULL;
				RetCode = Sock_CP_Map.GetNext((char **)&theDnNode, &Pos);
				if(theDnNode==NULL || RetCode<0)	//读到的是最后一个元素或者早已为空,下次将从头开始取
					break;
				if(theDnNode->SentQ.IsEmpty())	//检查下节点的已发送队列是否为空
				{
					RetCode = shutdown(theDnNode->TcpSock.sock, SHUT_RDWR);	//关闭连接,对应发送线程将退出
					if(RetCode)
					{
						sprintf(sSysEvent,"Error: Failed to shutdown the socket of DnNode[%d]!",theDnNode->NodeID);
						WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);   //写系统日志
					}
					AliveDnNode--;
					#ifdef DEBUG
					printf("\n SafeExit: Connection to DnNode[%d] is cut!\n",theDnNode->NodeID);
					#endif
					if(!AliveDnNode)	//最后一个下节点的连接被关闭后
					{
						if(DnRecvThr)
							pthread_kill(DnRecvThr, SIGUSR1);	//退出DnReceiver
						break;
					}
				}
			}//for(;;)
		}//if(AliveDnNode)

		if(AliveUpNode==0 && AliveDnNode==0)	//所有节点都已断开
			break;
	}//while(1)

	//退出上、下端接收队列轮询处理线程
	if(UpRecvQ_PollThr)
		pthread_kill(UpRecvQ_PollThr, SIGUSR2);
	if(DnRecvQ_PollThr)
		pthread_kill(DnRecvQ_PollThr, SIGUSR2);
	//退出上、下端已发送队列定时(轮询)线程
	if(UpSentQ_PollThr)
		pthread_kill(UpSentQ_PollThr, SIGUSR1);
	if(DnSentQ_PollThr)
		pthread_kill(DnSentQ_PollThr, SIGUSR1);
	strcpy(sSysEvent,"LOG: All connections have been cut! Backuping data in Queues...");
	WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);   //写系统日志

	//=======================保存队列中的数据包=========================
	CDnNode *DnNode[MAX_DNNODE];
	int DnNode_Num;
	int UpSaved = 0;
	while(1)
	{
		if(UpSaved < UPNODE_NUM)
		{
			for(int i=0; i<UPNODE_NUM; i++)
			{
				if(UpNode[i].ToExit==0 && UpNode[i].State)	//补充处理某些上节点在退出命令发出前连接已断的情况
				{
					 UpNode[i].ToExit=1;	//置退出标识
					 if(UpNode[i].ReadThr)
						 pthread_kill(UpNode[i].ReadThr, SIGUSR1);
					 if(UpNode[i].WriteThr)
						 pthread_kill(UpNode[i].WriteThr, SIGUSR1);
				}
				//上节点的收发线程都已退出时
				if(UpNode[i].ToExit!=2 && UpNode[i].ReadThr==0 && UpNode[i].WriteThr==0)
				{
					RecvBak = 0;
					RecvNum = UpNode[i].RecvQ->GetLen();
					if(RecvNum)	//接收队列不为空
					{
						//-----------接收队列备份------------
						memset(FileName,0,sizeof(FileName));
						sprintf(FileName,"%s%s%s",UpNode[i].UpQueueBak,UpNode[i].SP_Id,UpNode[i].UpRecvQ_File);
						RetCode=Qbackup->RWOpen(FileName, "ow");	//打开备份文件
						if(RetCode)
						{
							sprintf(sSysEvent,"Error[%d]: Opening %s file for backuping RecvQ of UpNode[%d].",RetCode,FileName,UpNode[i].NodeID);
							WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
						}
						while(1)
						{
							memset(&RUnit,0,sizeof(RUnit));
							if(UpNode[i].RecvQ->Get(RUnit)==false)
								break;
							PackType = ntohl(*(unsigned int *)(RUnit.Pack + 4));
							printf("\n UpSendQ_Backup:  PackType=%x, xxx=%x, deliver=%d. \n",PackType, *(int *)(RUnit.Pack + 4), CMPP_DELIVER);
							if((UpNode[i].Protocol==0 && PackType==CMPP_DELIVER) || (UpNode[i].Protocol==1 && PackType==REQUEST_ID_DELIVER))
							{
								//保存接收队列中的数据包
								RetCode = Qbackup->RecvQ_Backup(&RUnit);
								if(RetCode)
								{
									sprintf(sSysEvent,"Error[%d]: Failed to Backup RecvQ of UpNode[%d].",RetCode,UpNode[i].NodeID);
									WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
								}
								RecvBak++;
							}
						}//while(1)
						Qbackup->RWClose();	//关闭备份文件
					}

					SendBak = 0;
					SendNum = UpNode[i].SendQ->GetLen();
					if(SendNum)	//发送队列不为空
					{
						//-----------发送队列备份------------
						memset(FileName,0,sizeof(FileName));
						sprintf(FileName,"%s%s%s",UpNode[i].UpQueueBak,UpNode[i].SP_Id,UpNode[i].UpSendQ_File);
						RetCode = Qbackup->RWOpen(FileName, "ow");	//打开备份文件
						if(RetCode)
						{
							sprintf(sSysEvent,"Error[%d]: Opening %s file for backuping SendQ of UpNode[%d].",RetCode,FileName,UpNode[i].NodeID);
							WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
						}
						while(1)
						{
							memset(&SUnit,0,sizeof(SUnit));
							if(UpNode[i].SendQ->Get(SUnit)==false)
								break;
							PackType = ntohl(*(unsigned int *)(SUnit.Pack + 4));
							printf("\n UpSendQ_Backup:  PackType=%x, xxx=%x, submit=%d. \n",PackType, *(int *)(SUnit.Pack + 4), CMPP_SUBMIT);
							if((UpNode[i].Protocol==0 && PackType==CMPP_SUBMIT) || (UpNode[i].Protocol==1 && PackType==REQUEST_ID_SUBMIT))
							{
								//保存发送队列中的数据包
								RetCode = Qbackup->SendQ_Backup(&SUnit);
								if(RetCode)
								{
									sprintf(sSysEvent,"Error[%d]: Failed to Backup SendQ of UpNode[%d].",RetCode,UpNode[i].NodeID);
									WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
								}
								SendBak++;
							}
						}//while(1)
						Qbackup->RWClose();	//关闭备份文件
					}
					#ifdef DEBUG
					printf("\n SafeExit: Packets in RecvQ[%d/%d] and SendQ[%d/%d] of UpNode[%d] are saved!\n",RecvBak,RecvNum,SendBak,SendNum,UpNode[i].NodeID);
					#endif
					
					UpNode[i].ToExit=2;
					UpSaved++;
				}
			}//for
		}//if(UpSaved < UPNODE_NUM)

		//获取所有曾经上线的下节点
		DnNode_Num = Code_CP_Map.GetAllNode((char **)DnNode,MAX_DNNODE);
		for(int i=0; i<DnNode_Num; i++)
		{
			if(DnRecvThr==0 && DnNode[i]->SendThr==0)	//下节点的收发线程都已退出
			{
				RecvBak = 0;
				RecvNum = DnNode[i]->RecvQ->GetLen();
				if(RecvNum)	//接收队列不为空
				{
					//-----------接收队列备份------------
					memset(FileName,0,sizeof(FileName));
					sprintf(FileName,"%s%d%s",DnQueueBak,DnNode[i]->NodeID,DnRecvQ_File);
					RetCode = Qbackup->RWOpen(FileName, "ow");	//打开备份文件
					if(RetCode)
					{
						sprintf(sSysEvent,"Error[%d]: Opening %s file for backuping RecvQ of DnNode[%d].",RetCode,FileName,DnNode[i]->NodeID);
						WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
					}
					while(1)
					{
						memset(&RUnit,0,sizeof(RUnit));
						if(DnNode[i]->RecvQ->Get(RUnit)==false)
							break;
						PackType = ntohl(*(unsigned int *)(RUnit.Pack + 4));
						//printf("\n DnRecvQ_Backup:  PackType=%x, xxx=%x, submit=%d. \n",PackType, *(int *)(RUnit.Pack + 4), CMPP_SUBMIT);
						if(PackType==CMPP_SUBMIT)
						{
							//保存接收队列中的数据包
							RetCode = Qbackup->RecvQ_Backup(&RUnit);
							if(RetCode)
							{
								sprintf(sSysEvent,"Error[%d]: Failed to Backup RecvQ of DnNode[%d].",RetCode,DnNode[i]->NodeID);
								WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
							}
							RecvBak++;
						}
					}//while(1)
					Qbackup->RWClose();	//关闭备份文件
				}

				SendBak = 0;
				SendNum = DnNode[i]->SendQ->GetLen();
				if(SendNum)	//发送队列不为空
				{
					//-----------发送队列备份------------
					memset(FileName,0,sizeof(FileName));
					sprintf(FileName,"%s%d%s",DnQueueBak,DnNode[i]->NodeID,DnSendQ_File);
					RetCode = Qbackup->RWOpen(FileName, "ow");	//打开备份文件
					if(RetCode)
					{
						sprintf(sSysEvent,"Error[%d]: Opening %s file for backuping SendQ of DnNode[%d].",RetCode,FileName,DnNode[i]->NodeID);
						WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
					}
					while(1)
					{
						memset(&SUnit,0,sizeof(SUnit));
						if(DnNode[i]->SendQ->Get(SUnit)==false)
							break;
						PackType = ntohl(*(unsigned int *)(SUnit.Pack + 4));
						//printf("\n DnSendQ_Backup:  PackType=%x, xxx=%x, deliver=%d. \n",PackType, *(int *)(SUnit.Pack + 4), CMPP_DELIVER);
						if(PackType==CMPP_DELIVER)
						{
							//保存发送队列中的数据包
							RetCode = Qbackup->SendQ_Backup(&SUnit);
							if(RetCode)
							{
								sprintf(sSysEvent,"Error[%d]: Failed to Backup SendQ of DnNode[%d].",RetCode,DnNode[i]->NodeID);
								WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);
							}
							SendBak++;
						}
					}//while(1)
					Qbackup->RWClose();	//关闭备份文件
				}

				#ifdef DEBUG
				printf("\n SafeExit: Packets in RecvQ[%d/%d] and SendQ[%d/%d] of DnNode[%d] are saved!\n",RecvBak,RecvNum,SendBak,SendNum,DnNode[i]->NodeID);
				#endif

				int DelNum = Code_CP_Map.Delete(DnNode[i]->NodeID);	//从下节点映射表中清除
				if(DelNum!=1)
				{
					sprintf(sSysEvent,"Error: DelNum=[%d], Failed to Delete a DnNode[%d] in Code_CP_Map!",DelNum,theDnNode->NodeID);
					WrSystemLog->WriteLog(sSysEvent,SYSTEMLOG);   //写系统日志
				}
				delete DnNode[i];
			}
			else	//下节点的收发线程未完全退出
			{
				#ifdef DEBUG
				//printf("\n SafeExit: DnNode_Num=%d, DnRecvThr=%d, DnNode[%d]->SendThr=%d\n",DnNode_Num,(int)DnRecvThr,DnNode[i]->NodeID,(int)DnNode[i]->SendThr);
				#endif
			}
		}
		if(UpSaved==UPNODE_NUM && DnNode_Num==0)	//所有节点的队列数据保存完毕
			break;
		else
		{
			//printf("\n SafeExit: UpSaved=%d, DnNode_Num=%d.\n",UpSaved,DnNode_Num);
		}
		usleep(50000);
	}

	delete Qbackup;
	//sleep(2);
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -