浏览代码

#IQRV #comment 去除 uplog 模块

gifur 2 年之前
父节点
当前提交
3431f65c41
共有 5 个文件被更改,包括 0 次插入1278 次删除
  1. 0 35
      Module/mod_uplog/CMakeLists.txt
  2. 0 732
      Module/mod_uplog/UpLogFSM.cpp
  3. 0 289
      Module/mod_uplog/UpLogFSM.h
  4. 0 170
      Module/mod_uplog/mod_uplog.cpp
  5. 0 52
      Module/mod_uplog/mod_uplog.h

+ 0 - 35
Module/mod_uplog/CMakeLists.txt

@@ -1,35 +0,0 @@
-#实体命名
-define_module("uplog")
-
-#整个实体加载的文件
-set(${MODULE_PREFIX}_SRCS
-	mod_uplog.cpp
-	mod_uplog.h
-	UpLogFSM.cpp
-	UpLogFSM.h
-	)
-#设置版本
-set(MOD_VERSION_STRING "1.0.0-dev1")
-add_module_libraries(${MODULE_PREFIX} ${MODULE_NAME} ${MOD_VERSION_STRING})
-
-
-#附加包含的目录(DevHeadPath:)
-
-
-target_include_directories(${MODULE_NAME} PRIVATE
-	${ModuleCommonHeadPath}
-	${RVC_FRAMEWORK_INCLUDES_DIR}
-	${CONAN_INCLUDE_DIRS_JSONCPP}
-)
-
-target_link_directories(${MODULE_NAME} PRIVATE
-	${CONAN_LIB_DIRS_JSONCPP}
-)
-
-# 添加实体需要依赖的其他共享库(包括系统库):连接器包含的包
-
-set(${MODULE_PREFIX}_LIBS ${MODULE_BASE_ALL_LIBS} ${CONAN_PKG_LIBS_JSONCPP})
-
-target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})  
-
-deploy_module(${MODULE_PREFIX} ${MODULE_NAME})

+ 0 - 732
Module/mod_uplog/UpLogFSM.cpp

@@ -1,732 +0,0 @@
-#include "stdafx.h"
-#include "UpLogFSM.h"
-//#include "Event.h"
-#ifdef RVC_OS_WIN
-#else
-#include <sys/timeb.h>
-#endif
-
-UpLogFSM::UpLogFSM() : m_pConnection(NULL),m_isSendLog(false),m_branchSendLog(false),m_logTypeList("")
-{
-	InitializeCriticalSection(&cs);
-	InitializeCriticalSection(&csRec);
-	m_SendMode=0;//默认是单条传送
-	m_iSub=0;//订阅总数
-	m_iRec=0;//队列接收总数
-	m_iSend=0;//队列发送总数
-	m_iThrow=0;//队列丢弃总数
-	m_iFail=0;//发送失败总次数
-	m_iSucc=0;//发送成功总次数
-	m_iEachSend=0;//每次连接发送的数量
-	m_iEachMaxSend=100;//每次连接最大发送次数
-
-
-}
-
-UpLogFSM::~UpLogFSM()
-{
-	EnterCriticalSection(&cs);
-	while(true){
-		if(m_logList.empty()){
-			break;
-		}else{
-			log_t* dLog = (log_t*)(*m_logList.begin());//集合首个元素
-			m_logList.erase(m_logList.begin());//集合删除首元素
-			delLog(dLog);//释放内存
-		}
-	}
-	LeaveCriticalSection(&cs);
-
-	DeleteCriticalSection(&cs);
-	DeleteCriticalSection(&csRec);
-}
-
-void UpLogFSM::OnStateTrans( int iSrcState, int iDstState )
-{
-	printDebugLog(CSimpleStringA::Format("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState)));
-	//Dbg("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState));
-}
-
-void UpLogFSM::OnSysVarEvent( const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName )
-{
-}
-
-ErrorCodeEnum UpLogFSM::OnInit()
-{
-	AddStateHooker(this);
-	//......
-
-	CSmartPointer<IEntityFunction> spFunction = m_pEntity->GetFunction();
-	CSmartPointer<IConfigInfo> spConfig;
-	
-	ErrorCodeEnum Error = spFunction->OpenConfig(Config_CenterSetting, spConfig);
-	if (Error_Succeed == Error) 
-	{
-		int branchSendLog = 0;
-		Error = spConfig->ReadConfigValueInt("UpLog", "BranchSendLog", branchSendLog);//全分行是否上传日志
-		if (Error_Succeed == Error)
-		{
-			//Dbg("get BranchSendLog=%d from CenterSetting.ini", branchSendLog);
-			printDebugLog(CSimpleStringA::Format("get BranchSendLog=%d from CenterSetting.ini", branchSendLog));
-			m_branchSendLog = branchSendLog==1 ? true : false ;//整个分行所有终端是否需要上传日志标志位
-		} 
-		else
-		{
-			//Dbg("get [UpLog].BranchSendLog from CenterSetting.ini failed");
-			printDebugLog(CSimpleStringA::Format("get [UpLog].BranchSendLog from CenterSetting.ini failed"));
-
-		}
-
-		if(m_branchSendLog){
-			m_isSendLog=true;
-		}else{
-			CSimpleStringA TerminalList ="";
-			Error = spConfig->ReadConfigValue("UpLog", "TerminalList", TerminalList);//某些终端是否上传日志
-			if (Error_Succeed == Error)
-			{
-				//Dbg("get TerminalList=%s from CenterSetting.ini", TerminalList);
-				printDebugLog(CSimpleStringA::Format("get TerminalList=%s from CenterSetting.ini", TerminalList.GetData()));
-				CSystemStaticInfo systemStaticInfo;
-		
-				auto rc =  this->m_pEntity->GetFunction()->GetSystemStaticInfo(systemStaticInfo);
-				assert(rc == Error_Succeed);
-
-				CAutoArray<CSimpleStringA> tList = TerminalList.Split('|');
-				for(int i=0; i<tList.GetCount(); i++){
-					if(tList[i]==systemStaticInfo.strTerminalID){
-						m_isSendLog=true;
-						break;
-					}
-				}
-			} 
-			else
-			{
-				//Dbg("get [UpLog].TerminalList from CenterSetting.ini failed");
-				printDebugLog(CSimpleStringA::Format("get [UpLog].TerminalList from CenterSetting.ini failed"));
-
-			}
-		}
-
-		//Dbg("m_isSendLog = %d ",m_isSendLog);
-		printDebugLog(CSimpleStringA::Format("m_isSendLog = %d ",m_isSendLog));
-
-		CSimpleStringA LogTypeList ="";
-		Error = spConfig->ReadConfigValue("UpLog", "LogType", LogTypeList); //某些日志类型是否上传
-		if (Error_Succeed == Error)
-		{
-			//Dbg("get LogTypeList=%s from CenterSetting.ini", LogTypeList);
-			printDebugLog(CSimpleStringA::Format("get LogTypeList=%s from CenterSetting.ini", LogTypeList.GetData()));
-
-			CSimpleStringA temp = "";
-			if(LogTypeList==""){
-				//空值默认全部类型上传
-				char buff[10] ={0} ;
-				sprintf(buff,"%d;%d;%d;%d;",(int)Log_Event,(int)Log_Warning,(int)Log_Error,(int)Log_Debug);
-				temp +=buff;
-			}else{
-				//根据类型值组合上传类型Event|Warn|Debug|Error
-				CAutoArray<CSimpleStringA> tList = LogTypeList.Split('|');
-				for(int i=0; i<tList.GetCount(); i++){
-					if(tList[i]=="Event"){
-						char buff[4] ={0} ;
-						sprintf(buff,"%d;",(int)Log_Event);
-						temp +=buff;
-					}else if(tList[i]=="Warn"){
-						char buff[4] ={0} ;
-						sprintf(buff,"%d;",(int)Log_Warning);
-						temp +=buff;
-					}else if(tList[i]=="Debug"){
-						char buff[4] ={0} ;
-						sprintf(buff,"%d;",(int)Log_Debug);
-						temp +=buff;
-
-					}else if(tList[i]=="Error"){
-						char buff[4] ={0} ;
-						sprintf(buff,"%d;",(int)Log_Error);
-						temp +=buff;
-					}
-				}
-			}
-			
-			m_logTypeList = temp;
-			//Dbg("m_logTypeList =%s", m_logTypeList);
-			printDebugLog(CSimpleStringA::Format("m_logTypeList =%s", m_logTypeList.GetData()));
-
-		} 
-		else
-		{
-			//Dbg("get [UpLog].LogTypeList from CenterSetting.ini failed");
-			printDebugLog(CSimpleStringA::Format("get [UpLog].LogTypeList from CenterSetting.ini failed"));
-		}
-
-		int SendMode = 0;
-		Error = spConfig->ReadConfigValueInt("UpLog", "SendMode", SendMode); //发送模式:0 单条发送 1 批量发送(最大32k)
-		if (Error_Succeed == Error){
-			m_SendMode = SendMode;
-			//Dbg("get m_SendMode = %d", SendMode);
-			printDebugLog(CSimpleStringA::Format("m_SendMode = %d", SendMode));
-		}else{
-			//Dbg("get [UpLog].SendMode from CenterSetting.ini failed");
-			printDebugLog(CSimpleStringA::Format("get [UpLog].SendMode from CenterSetting.ini failed"));
-		}
-
-		if(m_SendMode==0){
-			m_iEachMaxSend =EACH_SEND_COUNT_SINGLE;
-		}else{
-			m_iEachMaxSend =EACH_SEND_COUNT_MULTI;
-		}
-		//Dbg("m_iEachConnSum = %d",m_iEachConnSum);
-		printDebugLog(CSimpleStringA::Format("m_iEachMaxSend = %d",m_iEachMaxSend));
-
-	}else{
-		//Dbg("open CenterSetting.ini failed");
-		printDebugLog(CSimpleStringA::Format("open CenterSetting.ini failed"));
-		return Error_Exception;
-	}
-
-	return Error_Succeed;
-}
-
-ErrorCodeEnum UpLogFSM::OnExit()
-{
-	return Error_Succeed;
-}
-
-void UpLogFSM::s0_on_entry()
-{
-	if(m_isSendLog){
-		PostEventLIFO(new FSMEvent(USER_EVT_JMP_CONNECT));//跳转到S1状态
-	}else{
-		Dbg("不需要上收日志数据,等待60s");
-		ScheduleTimer(1, 60000);
-	}
-		
-}
-
-void UpLogFSM::s0_on_exit()
-{
-	CancelTimer(1);
-}
-
-unsigned int UpLogFSM::s0_on_event( FSMEvent* event )
-{
-	if (event->iEvt == EVT_TIMER) 
-	{
-		if(m_isSendLog){
-			PostEventLIFO(new FSMEvent(USER_EVT_JMP_CONNECT));//跳转到S1状态
-		}else{
-			Dbg("不需要上收日志数据,等待60s");
-			ScheduleTimer(1, 60000);
-		}	
-	}
-	return 0;
-}
-
-
-void UpLogFSM::s1_on_entry()
-{
-	if (!m_pConnection) {
-		m_pConnection = new UpLogConnection(m_pEntity, this);
-		
-		if(m_pConnection->ConnectFromCentralSetting() && m_pConnection->IsConnectionOK()){
-			//创建成功
-		}else{
-			//创建失败
-			printDebugLog(CSimpleStringA::Format("连接日志上收分行服务失败"));
-			m_pConnection->Close();
-			m_pConnection->DecRefCount();
-			m_pConnection = NULL;
-		}
-	}
-	if (!m_pConnection) 
-	{
-		ScheduleTimer(2, 10000); // try 10 seconds later
-	}
-	else 
-	{
-		PostEventLIFO(new FSMEvent(USER_EVT_JMP_SENDLOG));//跳转S2状态
-	}
-}
-
-void UpLogFSM::s1_on_exit()
-{
-	CancelTimer(2);
-}
-
-unsigned int UpLogFSM::s1_on_event(FSMEvent* event)
-{
-	if (event->iEvt == EVT_TIMER)
-	{
-		m_pConnection = new UpLogConnection(m_pEntity, this);
-
-		if(m_pConnection->ConnectFromCentralSetting()&&m_pConnection->IsConnectionOK()){
-			//创建成功
-		}else{
-			printDebugLog(CSimpleStringA::Format("连接日志上收分行服务失败"));
-			m_pConnection->Close();
-			m_pConnection->DecRefCount();
-			m_pConnection = NULL;
-		}
-
-		if (!m_pConnection) 
-		{
-			ScheduleTimer(2, 10000); // try 10 seconds later
-		} 
-		else {
-			PostEventLIFO(new FSMEvent(USER_EVT_JMP_SENDLOG));//跳转S2状态
-		}
-	}
-	return 0;
-}
-
-void UpLogFSM::s2_on_entry()
-{
-	if(m_isSendLog){
-
-		if(m_logList.empty()){
-			PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//为空时,等待10s再传
-		}else{
-			m_iEachSend = 0;
-			//打印每次发送统计记录;
-			//Dbg("send log statistic m_iRec=%d , m_iThrow=%d , m_iSend=%d , m_iSucc=%d , m_iFail=%d",m_iRec,m_iThrow,m_iSend,m_iSucc,m_iFail);
-			int unSend = m_logList.size();
-			printDebugLog(CSimpleStringA::Format("send log statistic m_iRec=%d , m_iThrow=%d , UnSend=%d , m_iSend=%d , m_iSucc=%d , m_iFail=%d",m_iRec,m_iThrow,unSend,m_iSend,m_iSucc,m_iFail));
-			m_pConnection->SendLog();
-			m_iEachSend++;
-		}
-	}else{
-		PostEventLIFO(new FSMEvent(USER_EVT_JMP_START));//跳转S0状态
-	}
-}
-void UpLogFSM::s2_on_exit()
-{
-	CancelTimer(3);	
-}
-unsigned int UpLogFSM::s2_on_event(FSMEvent* event)
-{
-	if (event->iEvt == EVT_TIMER){
-
-		PostEventLIFO(new FSMEvent(USER_EVT_JMP_CONNECT));//跳转S1状态
-
-	}else if (event->iEvt == USER_EVT_UPLOG_ANS){
-		
-		UpLogAnsEvent *ans = (UpLogAnsEvent *)event;
-		
-		//发送个数控制长连接时间
-		if (ans->m_reply.ResultCode == UpLogCtlCode::Finish) 
-		{
-			m_iSucc++;//成功		
-		}else if (ans->m_reply.ResultCode == UpLogCtlCode::Error) 
-		{
-			m_iFail++;//失败
-		}
-
-		if(m_iEachSend<m_iEachMaxSend){
-			if(m_logList.empty()){
-				//Dbg("返回报文结果:%d",ans->m_reply.ResultCode);
-				Dbg("队列已空");
-				//printDebugLog(CSimpleStringA::Format("返回报文结果:%d",ans->m_reply.ResultCode));//不能加入队列,否则不断循环
-				PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//为空时,等待10s再传
-			}else{
-				m_pConnection->SendLog();
-				m_iEachSend++;
-			}
-		}else{
-			PostEventLIFO(new FSMEvent(USER_EVT_DISCONNECT_SUCC));//正常退出
-		}
-
-	}else if (event->iEvt == USER_EVT_DISCONNECT_SUCC) {
-		//正常退出,等待3s时间返回S1
-		if(m_pConnection!=NULL){
-			m_pConnection->Close();
-			m_pConnection->DecRefCount();
-			m_pConnection = NULL;
-		}
-		ScheduleTimer(3, CONNECT_SUCC_WAIT_TIME); // try 3 seconds later
-	}else if (event->iEvt == USER_EVT_DISCONNECT_FAIL) {
-		//异常退出,等待10s时间返回S1
-		if(m_pConnection!=NULL){
-			m_pConnection->Close();
-			m_pConnection->DecRefCount();
-			m_pConnection = NULL;
-		}
-		ScheduleTimer(3, CONNECT_FAIL_WAIT_TIME); // try 10 seconds later
-	}
-	
-	return 0;
-}
-
-void UpLogFSM::addUplog( log_t* logt )
-{ //加锁,队列满了,把前面的丢弃,新的补充进来,注意释放内存空间
-	EnterCriticalSection(&cs);
-	if(m_logList.size()>=UPLOG_MAX_COUNT){
-		//Dbg("queue is full,delete log,EntityName=%s,Msg=%s,SN=%d",dLog->EntityName,dLog->Msg,dLog->SN);
-		log_t* dLog = (log_t*)(*m_logList.begin());//集合首个元素
-		m_logList.erase(m_logList.begin());//集合删除首元素
-		delLog(dLog);//释放内存
-		m_iThrow++;
-	}
-	m_logList.push_back(logt);//加入队列
-
-	LeaveCriticalSection(&cs);
-
-
-}
-
-log_t* UpLogFSM::removeUplog()
-{//加锁,取出先进的队列日志,注意释放内存空间
-	log_t* dLog = NULL;
-	EnterCriticalSection(&cs);
-	if(m_logList.empty()){
-
-	}else{
-		dLog = (log_t*)(*m_logList.begin());//集合首个元素
-		m_logList.erase(m_logList.begin());//集合删除首元素
-	}
-	LeaveCriticalSection(&cs);
-	return dLog;//返回
-}
-
-
-bool UpLogFSM::isType(const LogTypeEnum eLogTyp)
-{
-		char buff[4] ={0} ;
-		sprintf(buff,"%d",(int)eLogTyp);
-		if(m_logTypeList.IndexOf(buff)==-1){
-			return false;
-		}else{
-			return true;
-		}
-}
-
-void UpLogFSM::delLog( log_t* logt )
-{
-	if(logt==NULL){
-		return;
-	}
-	if(logt->EntityName!=NULL){
-
-		free(logt->EntityName);
-		logt->EntityName=NULL;
-	}
-	if(logt->Msg!=NULL){
-
-		free(logt->Msg);
-		logt->Msg=NULL;
-	}
-	if(logt->TerminalNo!=NULL){
-
-		free(logt->TerminalNo);
-		logt->TerminalNo=NULL;
-	}
-	if(logt->LogTime!=NULL){
-
-		free(logt->LogTime);
-		logt->LogTime=NULL;
-	}
-	if(logt->Item!=NULL){
-
-		free(logt->Item);
-		logt->Item=NULL;
-	}
-	if(logt->SysCode!=NULL){
-
-		free(logt->SysCode);
-		logt->SysCode=NULL;
-	}
-	if(logt->UserCode!=NULL){
-
-		free(logt->UserCode);
-		logt->UserCode=NULL;
-	}
-
-	delete logt;
-	logt=NULL;
-	return;
-}
-
-char* UpLogFSM::mallocStr( const char* s)
-{
-	char* temp =NULL;
-	if(s && (temp=(char*)malloc(strlen(s)+1))){
-		memset(temp,0,strlen(s)+1);
-		strcpy(temp,s);
-	}
-	return temp;
-}
-
-int UpLogFSM::getEntityRow( const char* entityName )
-{
-	if(entityName==NULL){
-		return 0;
-	}
-	CSimpleStringA findstr = entityName;
-	map<CSimpleString,int>::iterator iter;
-	iter = m_entityRowSet.find(findstr);
-	if(iter!=m_entityRowSet.end()){
-		(iter->second)++;
-		return iter->second;
-	}else{
-		m_entityRowSet.insert(make_pair(findstr,1));
-		return 1;
-	}
-
-	
-}
-
-
-bool UpLogFSM::getJsonStr( UpLogReq1* req )
-{	
-	//单条获取
-	//Dbg("队列消息数目=%d",m_logList.size());
-	//printDebugLog(CSimpleStringA::Format("队列消息数目=%d",m_logList.size()));
-	log_t* logt = removeUplog();//注意释放内存
-	if(logt==NULL){
-		return false;
-	}else{
-		//单条记录转换为json报文
-		Json::Value root;
-		Json::Value arraylist;//消息列表
-		Json::Value MsgObject;//消息对象
-		Json::FastWriter fw;//写入对象
-		root["interface"]="singleLog";
-		MsgObject["TerminalNo"]= logt->TerminalNo;
-		MsgObject["EntityName"]= logt->EntityName;
-		MsgObject["Item"]= logt->Item;
-		MsgObject["Time"]= logt->LogTime;
-		MsgObject["TimeSn"]= logt->SN;
-		MsgObject["SysCode"]= logt->SysCode;
-		MsgObject["UserCode"]= logt->UserCode;
-		MsgObject["LogType"]= logt->LogType;
-		MsgObject["Level"]= logt->Level;
-		MsgObject["msg"]= logt->Msg;
-		int i=0;
-		arraylist[i]= MsgObject;
-		root["msgList"] = arraylist;
-		string jsonStr = fw.write(root);
-		strncpy(req->TerminalNo,logt->TerminalNo,sizeof(req->TerminalNo)-1);//拷贝终端号
-		delLog(logt);//释放内存
-		//Dbg("转换的json报文,len=%d,内容=%s",jsonStr.length(),jsonStr.c_str());
-
-		if(!jsonStr.empty()){				
-			req->logLen= jsonStr.length();
-			strncpy(req->logdata,jsonStr.c_str(),sizeof(req->logdata)-1);//最大不超过2k
-			return true;
-		}else{
-			return false;
-		}
-	}
-}
-
-
-bool UpLogFSM::getJsonStr( UpLogReq2* req )
-{	
-	//动态根据接口长度组装json报文
-
-	int i = 0;
-	Json::Value root;
-	Json::Value arraylist;//消息列表
-	Json::FastWriter fw;//写入对象
-	root["interface"]="multiLog";
-	string jsonStr="" ;
-
-	while(true){
-		log_t* logt = removeUplog();//注意释放内存
-		if(logt==NULL){
-			break;
-		}else{
-			Json::Value MsgObject;//消息对象
-			MsgObject["TerminalNo"]= logt->TerminalNo;
-			MsgObject["EntityName"]= logt->EntityName;
-			MsgObject["Item"]= logt->Item;
-			MsgObject["Time"]= logt->LogTime;
-			MsgObject["TimeSn"]= logt->SN;
-			MsgObject["SysCode"]= logt->SysCode;
-			MsgObject["UserCode"]= logt->UserCode;
-			MsgObject["LogType"]= logt->LogType;
-			MsgObject["Level"]= logt->Level;
-			MsgObject["msg"]= logt->Msg;
-			arraylist[i]=MsgObject;
-			root["msgList"] = arraylist;
-			jsonStr = fw.write(root);//动态增长
-			//Dbg("jsonStr lenth is %d",jsonStr.length());
-			strncpy(req->TerminalNo,logt->TerminalNo,sizeof(req->TerminalNo)-1);//拷贝终端号
-			delLog(logt);//释放内存
-			//Dbg("转换的json报文,len=%d,内容=%s",jsonStr.length(),jsonStr.c_str());
-			if(jsonStr.length()>14*1024){
-				break;
-			}else{
-				i++;//加一
-				
-			}
-		}
-	}
-	Dbg("一次发送=%d",i);
-	//printDebugLog(CSimpleStringA::Format("一次发送条数=%d",i));//不能加入发送队列,否则不断循环
-
-	if(!jsonStr.empty()){
-		//Dbg("转换的json报文:%s",jsonStr.c_str());
-		req->logLen = jsonStr.length();
-		strncpy(req->logdata,jsonStr.c_str(),sizeof(req->logdata)-1);//最大不超过16k
-		return true;
-	}else{
-		return false;
-	}	
-}
-
-//使用此方法注意不要陷入死循环加入日志到队列中
-void UpLogFSM::printDebugLog( const char* debugStr )
-{
-	
-	Dbg("uplog:%s",debugStr);
-
-	//主动添加到消息队列中
-	string entityName = this->m_pEntity->GetEntityName();
-	log_t* logt = new log_t();
-	memset(logt,0,sizeof(log_t));
-
-	bool succ = true;
-
-	CSystemStaticInfo systemStaticInfo;
-	CSmartPointer<IEntityFunction> spFunction = m_pEntity->GetFunction();
-	ErrorCodeEnum Error = spFunction->GetSystemStaticInfo(systemStaticInfo);
-	char* cTerminalNo=NULL;
-	if(Error_Succeed == Error){
-		cTerminalNo = mallocStr(systemStaticInfo.strTerminalID.GetData());
-	}else{
-		string temp = "0000000000";
-		cTerminalNo = mallocStr(temp.c_str());
-	}
-
-	if(cTerminalNo!=NULL){
-		logt->TerminalNo = cTerminalNo;//终端号,记得释放
-	}else{
-		succ=false;
-	}
-
-	
-	char* cEntityName = mallocStr(entityName.c_str());
-
-	if(cEntityName!=NULL){
-		logt->EntityName = cEntityName;//实体名,记得释放
-	}else{
-		succ=false;
-	}
-
-
-
-	char* clogTime = (char*)malloc(30);
-	if(clogTime!=NULL){
-		memset(clogTime,0,30);//2020-20-20 12:12:12.100 日志时间,记得释放
-#ifdef RVC_OS_WIN
-		SYSTEMTIME st ;
-		GetLocalTime(&st);
-		sprintf(clogTime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-#else
-		struct timeb stime = { 0, 0 };
-		tm nowTm = { 0 };
-		ftime(&stime);
-		localtime_r(&stime.time, &nowTm);
-		sprintf(clogTime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", nowTm.tm_year + 1900, nowTm.tm_mon + 1, nowTm.tm_mday, nowTm.tm_hour, nowTm.tm_min, nowTm.tm_sec, stime.millitm);
-#endif
-		logt->LogTime =clogTime;
-	}else{
-		succ=false;
-	}
-
-
-	char* cMsg = mallocStr(debugStr);
-
-	if(cMsg!=NULL){
-		logt->Msg = cMsg;//日志消息,记得释放
-	}else{
-		succ=false;
-	}
-
-
-	
-
-	char* cEntityInstanceID = (char*)malloc(20);
-
-	if (cEntityInstanceID!=NULL)
-	{
-		memset(cEntityInstanceID,0,20);
-		CEntityRunInfo eri = {0};
-		ErrorCodeEnum ec = GetEntityBase()->GetFunction()->GetSelfEntityRunInfo(eri);
-		if(ec == Error_Succeed)
-		{
-#ifdef RVC_OS_WIN
-			ultoa(eri.dwEntityInstanceID, cEntityInstanceID, 10);//实体ID,记得释放
-#else
-			sprintf(cEntityInstanceID, "%ul", eri.dwEntityInstanceID);
-#endif
-
-			
-			logt->Item = cEntityInstanceID;
-		}else{
-			logt->Item = cEntityInstanceID;//实体ID,记得释放
-		}
-
-	}else{
-		succ=false;
-	}
-
-
-
-	char* cSysError = (char*)malloc(20);
-	if (cSysError!=NULL)
-	{
-		memset(cSysError,0,20);
-#ifdef RVC_OS_WIN
-		ultoa(0xffff,cSysError,16);//系统errorcode,记得释放
-#else
-		sprintf(cSysError, "%x", 0xffff);
-#endif
-		logt->SysCode=cSysError;
-	}else{
-		succ=false;
-	}
-
-
-	char* cUserCode = (char*)malloc(20);
-	if (cUserCode!=NULL)
-	{
-		memset(cUserCode,0,20);
-#ifdef RVC_OS_WIN
-		ultoa(0xffff, cUserCode, 16);//用户定义Usercode,记得释放
-#else
-		sprintf(cUserCode, "%x", 0xffff);
-#endif
-		
-		logt->UserCode = cUserCode;
-	}else{
-		succ=false;
-	}
-
-
-	logt->LogType = (int)LogTypeEnum::Log_Debug;
-
-	logt->Level = (int)SeverityLevelEnum::Severity_Low;
-
-	int iRow = getEntityRow(entityName.c_str());
-
-	logt->SN =iRow;
-
-	addRecSum();
-	if(!succ){
-		delLog(logt);//删除元素内存
-		return;
-	}else{
-		addUplog(logt);//加入日志到列表
-	}
-}
-
-
-
-void UpLogFSM::addRecSum()
-{
-	EnterCriticalSection(&csRec);
-	m_iRec++;
-	LeaveCriticalSection(&csRec);
-}
-

+ 0 - 289
Module/mod_uplog/UpLogFSM.h

@@ -1,289 +0,0 @@
-#ifndef RVC_MOD_UPLOG_FSM_H_
-#define RVC_MOD_UPLOG_FSM_H_
-
-#include "SpBase.h"
-#include "SpFSM.h"
-#include "SpSecureClient.h"
-#include <map>
-#include <vector>
-#include "json/json.h"
-
-
-
-#define USER_EVT_JMP_CONNECT			EVT_USER+1
-#define USER_EVT_JMP_START				EVT_USER+2
-#define USER_EVT_JMP_SENDLOG			EVT_USER+3
-#define USER_EVT_DISCONNECT_SUCC		EVT_USER+4
-#define USER_EVT_UPLOG_ANS				EVT_USER+5
-#define USER_EVT_DISCONNECT_FAIL		EVT_USER+6
-
-
-
-struct UpLogReq1
-{
-	char TerminalNo[16];
-	int logLen;
-	char logdata[2048];
-};
-
-struct UpLogReq2
-{
-	char TerminalNo[16];
-	int logLen;
-	char logdata[32768];
-};
-
-
-struct UpLogReply
-{
-	int ResultCode;
-};
-
-
-#pragma pack()
-
-
-enum UpLogCtlCode
-{
-	Finish = 0,             //完成
-	Error = 1,              //错误
-};
-
-struct log_t 
-{
-	char* TerminalNo;//终端号
-	char* EntityName;//实体名
-	char* Item;//实体ID
-	char* LogTime;//日志时间
-	int SN;//各实体记录行号
-	char* SysCode;//系统错误码
-	char* UserCode;//用户错误码
-	int LogType;//日志类型
-	int Level;//日志级别
-	char* Msg;//日志描述
-};
-
-const int UPLOG_MAX_COUNT = 5000;//队列长度
-const int EACH_SEND_COUNT_SINGLE = 200;//单条发送每次最大发送次数
-const int EACH_SEND_COUNT_MULTI = 10;//批量发送每次发送次数
-const int CONNECT_FAIL_WAIT_TIME=10*1000;
-const int CONNECT_SUCC_WAIT_TIME=3*1000;
-
-struct UpLogAnsEvent : public FSMEvent 
-{
-	UpLogAnsEvent(BYTE *pBuf, int nLen) : FSMEvent(USER_EVT_UPLOG_ANS) 
-	{
-		memcpy(&m_reply, pBuf, sizeof(UpLogReply));
-	}
-	virtual ~UpLogAnsEvent() {}
-	UpLogReply m_reply;
-};
-
-
-class UpLogConnection;
-
-class UpLogFSM : public FSMImpl<UpLogFSM>, public IFSMStateHooker, public ISysVarListener
-{
-public:
-	enum {s0,s1,s2,s3};
-
-	BEGIN_FSM_STATE(UpLogFSM)
-		FSM_STATE_ENTRY(s0,"Start",s0_on_entry,s0_on_exit,s0_on_event)
-		FSM_STATE_ENTRY(s1, "Connect", s1_on_entry, s1_on_exit, s1_on_event)
-		FSM_STATE_ENTRY(s2, "sendLog", s2_on_entry, s2_on_exit, s2_on_event)
-		END_FSM_STATE()
-
-		BEGIN_FSM_RULE(UpLogFSM,s0)
-		FSM_RULE_ENTRY_ANY(s0, s1, USER_EVT_JMP_CONNECT)
-		FSM_RULE_ENTRY_ANY(s1, s2, USER_EVT_JMP_SENDLOG)
-		FSM_RULE_ENTRY_ANY(s2, s0, USER_EVT_JMP_START)
-		FSM_RULE_ENTRY_ANY(s2, s1, USER_EVT_JMP_CONNECT)
-		END_FSM_RULE()
-
-	UpLogFSM();
-	~UpLogFSM();
-
-	virtual void OnStateTrans(int iSrcState, int iDstState);
-
-	virtual void OnSysVarEvent(const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName);
-
-	virtual ErrorCodeEnum OnInit();
-	virtual ErrorCodeEnum OnExit();
-
-	void s0_on_entry();
-	void s0_on_exit();
-	unsigned int s0_on_event(FSMEvent* event);
-
-	void s1_on_entry();
-	void s1_on_exit();
-	unsigned int s1_on_event(FSMEvent* event);
-
-	void s2_on_entry();
-	void s2_on_exit();
-	unsigned int s2_on_event(FSMEvent* event);
-	
-public:
-	//加锁添加日志
-	void addUplog(log_t* logt);
-	//加锁取出日志
-	log_t* removeUplog();
-	bool isSend(){
-		return m_isSendLog;
-	}
-	bool isType(const LogTypeEnum eLogType);//是否符合日志定义类型
-	void delLog(log_t* logt);//删除释放日志内存
-	char* mallocStr( const char* s);
-	int getEntityRow (const char* entityName);
-	bool getJsonStr(UpLogReq1* req);//0: 无数据 1:成功 2:获取jsonstr失败
-	bool getJsonStr(UpLogReq2* req);//0: 无数据 1:成功 2:获取jsonstr失败
-	void printDebugLog(const char* debugStr);//内部使用的一个打印日志方法
-	void addRecSum();
-
-private:
-	CRITICAL_SECTION cs;//队列锁
-	CRITICAL_SECTION csRec;//添加计数锁
-	UpLogConnection *m_pConnection;
-	CSimpleString m_logTypeList;//日志级别,集中配置文件
-	bool m_isSendLog;//该终端是否上传日志
-	bool m_branchSendLog;//分行上传日志开关,集中配置文件
-	map<CSimpleString,int> m_entityRowSet;//各实体记录行号map
-	
-	
-
-public:
-	int m_SendMode;//发送模式:0 单条发送(2k) 1 批量发送(最大32k)
-	int m_iEachMaxSend;//每次连接最大发送次数
-	vector<log_t*> m_logList;//日志记录列表
-	//统计数量
-	int m_iSub;//订阅总数
-	int m_iRec;//队列接收总数
-	int m_iSend;//队列发送总数
-	int m_iThrow;//队列丢弃总数
-	int m_iFail;//发送失败总次数
-	int m_iSucc;//发送成功总次数
-	int m_iEachSend;//每次连接发送的数量
-
-};
-
-class UpLogConnection : public SpSecureClient
-{
-public:
-	UpLogConnection(CEntityBase *pEntity, UpLogFSM *pFSM) : SpSecureClient(pEntity), m_pFSM(pFSM) {}
-	virtual ~UpLogConnection() {}
-
-	void SendLog()
-	{
-		m_pFSM->m_iSend++;
-		CSmartPointer<IPackage> pkt = CreateNewPackage("UPLOG");
-		//Dbg("m_SendMode=%d",m_pFSM->m_SendMode);
-		//m_pFSM->printDebugLog(CSimpleStringA::Format("m_SendMode=%d",m_pFSM->m_SendMode));
-		if(m_pFSM->m_SendMode==0){
-			//单条数据
-			UpLogReq1* req1 = new UpLogReq1();
-			memset(req1, 0, sizeof(UpLogReq1));
-			if(m_pFSM->getJsonStr(req1)){
-				pkt->AddStruct("LOGREQ1", false, true, (LPBYTE)req1, sizeof(UpLogReq1));
-				if (SendPackage(pkt) == "")
-				{
-					//Dbg("send uplog fail:sendPackage fail");
-					m_pFSM->printDebugLog(CSimpleStringA::Format("send uplog fail:sendPackage fail"));
-					m_pFSM->m_iFail++;
-					m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//失败,等下次发送
-				}
-			}else{
-				//Dbg("send uplog fail:get jsonStr fail");
-				m_pFSM->printDebugLog(CSimpleStringA::Format("send uplog fail:get jsonStr fail"));
-				m_pFSM->m_iFail++;
-				m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//失败,等下次发送
-			}
-			if(req1!=NULL)
-			{
-				delete req1;
-			}
-
-		}else{
-			//多条数据
-			UpLogReq2* req2 = new UpLogReq2();
-			memset(req2, 0, sizeof(UpLogReq2));
-			if(m_pFSM->getJsonStr(req2)){
-				pkt->AddStruct("LOGREQ2", false, true, (LPBYTE)req2, sizeof(UpLogReq2));
-				if (SendPackage(pkt) == "")
-				{
-					//Dbg("send uplog fail:sendPackage fail");
-					m_pFSM->printDebugLog(CSimpleStringA::Format("send uplog fail:sendPackage fail"));
-					m_pFSM->m_iFail++;
-					m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//失败,等下次发送
-				}
-			}else{
-				//Dbg("send uplog fail:get jsonStr fail");
-				m_pFSM->printDebugLog(CSimpleStringA::Format("send uplog fail:get jsonStr fail"));
-				m_pFSM->m_iFail++;
-				m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));//失败,等下次发送
-			}
-			if(req2!=NULL)
-			{
-				delete req2;
-			}
-		}			
-	}
-protected:
-	virtual void OnPkgAnswer(const CSmartPointer<IPackage> &pRecvPkg) {
-		string serviceCode = pRecvPkg->GetServiceCode();
-		if (serviceCode == "UPLOG") 
-		{
-			//Dbg("receive pkg");
-			DWORD dwSysCode, dwUserCode;
-			string strErrMsg;
-			ErrorCodeEnum rc = Error_Succeed;
-			if (pRecvPkg->GetErrMsg(dwSysCode, dwUserCode, strErrMsg))
-			{
-				rc = (ErrorCodeEnum)dwSysCode;
-				LogWarn(Severity_Middle, rc, dwUserCode, CSimpleStringA::Format("create up packet Fail!, %s", strErrMsg.c_str()));
-				m_pFSM->printDebugLog(CSimpleStringA::Format("create up packet Fail!, %s", strErrMsg.c_str()));//记录到日志中
-				m_pFSM->m_iFail++;//失败
-				OnDisconnect();//10s
-
-			}else{
-				int nLen = pRecvPkg->GetStructLen("LOGRET");
-				if (nLen > 0) 
-				{
-					BYTE *pBuf = new BYTE[nLen];
-					memset(pBuf, 0, nLen);
-					int nArrayNum = 0;
-					if (pRecvPkg->GetStructData("LOGRET", pBuf, &nLen, &nArrayNum)) 
-					{
-						FSMEvent *evt = new UpLogAnsEvent(pBuf, nLen);
-						m_pFSM->PostEventFIFO(evt);//跳转到结果判断
-					} 
-					else 
-					{
-						//Dbg("create invalid UpLog upans packet!");
-						m_pFSM->printDebugLog(CSimpleStringA::Format("create invalid UpLog upans packet!"));
-
-						m_pFSM->m_iFail++;//失败
-						OnDisconnect();//10s
-					}
-					delete[] pBuf;
-				}else{
-					//nlen增加跳出分支
-					//Dbg("upans packet len is error len=%d",nLen);
-					m_pFSM->printDebugLog(CSimpleStringA::Format("upans packet len is error len=%d",nLen));
-					m_pFSM->m_iFail++;//失败
-					OnDisconnect();//10s
-				}
-			} 
-		}else{
-			//Dbg("unknown service code! code= %s",serviceCode.c_str());
-			m_pFSM->printDebugLog(CSimpleStringA::Format("unknown service code! code= %s",serviceCode.c_str()));
-			OnDisconnect();//失败//10s
-		}
-	};
-	virtual void OnDisconnect() 
-	{
-		m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT_FAIL));
-	}
-
-private:
-	UpLogFSM *m_pFSM;
-};
-#endif //RVC_MOD_UPLOG_FSM_H_

+ 0 - 170
Module/mod_uplog/mod_uplog.cpp

@@ -1,170 +0,0 @@
-#include "stdafx.h"
-#include "mod_uplog.h"
-#ifdef RVC_OS_WIN
-#else
-#include <sys/timeb.h>
-#endif
-
-void CUpLogEntity::OnLog(const CAutoArray<CUUID> &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
-	const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID, 
-	const CAutoArray<DWORD> &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage, const linkContext& pLinkInfo)
-{
-	m_fsm.m_iSub++;
-
-	//发送开关打开并且符合类型
-	if(m_fsm.isSend()&&m_fsm.isType(eLogType)){
-		
-		if(strcmp(pszEntityName,"UpLog")==0){
-			//Dbg("接收到来自uplog实体日志");
-			return;
-		}
-		log_t* logt = new log_t();
-		memset(logt,0,sizeof(log_t));
-
-		bool succ = true;
-
-		CSystemStaticInfo systemStaticInfo;
-		CSmartPointer<IEntityFunction> spFunction = GetFunction();
-		ErrorCodeEnum Error = spFunction->GetSystemStaticInfo(systemStaticInfo);
-		char* cTerminalNo=NULL;
-		if(Error_Succeed == Error){
-			cTerminalNo = m_fsm.mallocStr(systemStaticInfo.strTerminalID.GetData());
-		}else{
-			string temp = "0000000000";
-			cTerminalNo = m_fsm.mallocStr(temp.c_str());
-		}
-
-		if(cTerminalNo!=NULL){
-			logt->TerminalNo = cTerminalNo;//终端号,记得释放
-		}else{
-			succ=false;
-		}
-
-		
-		char* cEntityName = m_fsm.mallocStr(pszEntityName);
-
-		if(cEntityName!=NULL){
-			logt->EntityName = cEntityName;//实体名,记得释放
-		}else{
-			succ=false;
-		}
-
-		
-
-		char* clogTime = (char*)malloc(30);
-		if(clogTime!=NULL){
-			memset(clogTime,0,30);//2020-20-20 12:12:12.100 日志时间,记得释放
-#ifdef RVC_OS_WIN
-			SYSTEMTIME st;
-			GetLocalTime(&st);
-			sprintf(clogTime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-#else
-			struct timeb stime = { 0, 0 };
-			tm nowTm = { 0 };
-			ftime(&stime);
-			localtime_r(&stime.time, &nowTm);
-			sprintf(clogTime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", nowTm.tm_year + 1900, nowTm.tm_mon + 1, nowTm.tm_mday, nowTm.tm_hour, nowTm.tm_min, nowTm.tm_sec, stime.millitm);
-#endif
-			logt->LogTime =clogTime;
-		}else{
-			succ=false;
-		}
-
-
-		char* cMsg = m_fsm.mallocStr(pszMessage);
-
-		if(cMsg!=NULL){
-			logt->Msg = cMsg;//日志消息,记得释放
-		}else{
-			succ=false;
-		}
-
-
-		
-		
-		char* cEntityInstanceID = (char*)malloc(20);
-		if (cEntityInstanceID!=NULL)
-		{
-			memset(cEntityInstanceID,0,20);
-#ifdef RVC_OS_WIN
-			ultoa(dwEntityInstanceID, cEntityInstanceID, 10);//实体ID,记得释放
-#else
-			sprintf(cEntityInstanceID, "%ul", dwEntityInstanceID);
-#endif
-			
-			logt->Item = cEntityInstanceID;
-		}else{
-			succ=false;
-		}
-
-
-		char* cSysError = (char*)malloc(20);
-		if (cSysError!=NULL)
-		{
-			memset(cSysError,0,20);
-#ifdef RVC_OS_WIN
-			ultoa(dwSysError,cSysError,16);//系统errorcode,记得释放
-#else
-			sprintf(cSysError, "%x", dwSysError);
-#endif
-			logt->SysCode=cSysError;
-		}else{
-			succ=false;
-		}
-
-
-		char* cUserCode = (char*)malloc(20);
-		if (cUserCode!=NULL)
-		{
-			memset(cUserCode,0,20);
-#ifdef RVC_OS_WIN
-			ultoa(dwUserCode,cUserCode,16);//用户定义Usercode,记得释放
-#else
-			sprintf(cUserCode, "%x", dwUserCode);
-#endif
-			logt->UserCode = cUserCode;
-		}else{
-			succ=false;
-		}
-
-
-		logt->LogType = (int)eLogType;
-
-		logt->Level = (int)eLevel;
-
-		int iRow = m_fsm.getEntityRow(pszEntityName);
-		logt->SN =iRow;
-		//Dbg("add log,LogTime=%s,EntityName=%s,Msg=%s,LogType=%d,TerminalNo=%s,SysCode=%s,UserCode=%s,SN=%d",logt->LogTime,logt->EntityName,logt->Msg,logt->LogType,logt->TerminalNo,logt->SysCode,logt->UserCode,logt->SN);
-		
-		m_fsm.addRecSum();
-		if(!succ){
-			m_fsm.delLog(logt);//删除元素内存
-			return;
-		}else{
-			m_fsm.addUplog(logt);//加入日志到列表
-		}
-		//每订阅500次打印一下
-		if(m_fsm.m_iSub%500==0){
-			m_fsm.printDebugLog(CSimpleStringA::Format("订阅总数=%d, 接收总数=%d, 抛弃总数=%d, 当前未发送数目=%d,",m_fsm.m_iSub, m_fsm.m_iRec ,m_fsm.m_iThrow ,m_fsm.m_logList.size()));
-		}
-	}else{
-		return;
-	}
-	return;
-}
-
-void CUpLogEntity::OnSelfTest( EntityTestEnum eTestType,CSmartPointer<ITransactionContext> pTransactionContext )
-{
-	if (Test_ShakeHand == eTestType)
-	{
-		pTransactionContext->SendAnswer(Error_Succeed); 
-	}
-}
-
-
-
-
-SP_BEGIN_ENTITY_MAP()
-	SP_ENTITY(CUpLogEntity)
-SP_END_ENTITY_MAP()
-

+ 0 - 52
Module/mod_uplog/mod_uplog.h

@@ -1,52 +0,0 @@
-#ifndef RVC_MOD_UPLOG_H_
-#define RVC_MOD_UPLOG_H_
-
-#include "stdafx.h"
-#include "SpBase.h"
-#include "SpIni.h"
-#include "UpLogFSM.h"
-#include "EventCode.h"
-
-class CUpLogEntity : public CEntityBase,public ILogListener
-{
-public:
-	CUpLogEntity(){}
-	virtual ~CUpLogEntity() {}
-	virtual const char *GetEntityName() const { return "UpLog"; }
-
-	virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs,CSmartPointer<ITransactionContext> pTransactionContext) 
-	{
-		ErrorCodeEnum Error = Error_Succeed;
-		Error = m_fsm.Init(this);
-		//添加日志订阅接口
-		if(Error_Succeed==Error){
-			Error = GetFunction()->SubscribeLog(m_uuidPtr,this,Log_Ignore,Severity_None,Error_IgnoreAll,-2,NULL,false);
-			if(Error_Succeed!=Error){
-				LogError(Severity_High, Error, 0, "entity uplog SubscribeLog is  fail");
-			}
-
-		}else{
-			LogError(Severity_High, Error, 0, "entity uplog preStart is  fail");
-		}
-		pTransactionContext->SendAnswer(Error);
-	}
-
-	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext) 
-	{ 
-		pTransactionContext->SendAnswer(Error_Succeed);
-		//取消日志订阅接口
-		GetFunction()->UnsubscribeLog(m_uuidPtr);
-
-	}
-	virtual void OnSelfTest(EntityTestEnum eTestType,CSmartPointer<ITransactionContext> pTransactionContext) ;
-	virtual void OnLog(const CAutoArray<CUUID> &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
-		const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID, 
-		const CAutoArray<DWORD> &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage, const linkContext& pLinkInfo);
-
-	
-private:
-	UpLogFSM m_fsm;
-	CUUID m_uuidPtr;
-	
-};
-#endif //RVC_MOD_UPLOG_H_