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

📄 gateserver.cc

📁 EPICS CA gateway, base on channel access protocol
💻 CC
📖 第 1 页 / 共 5 页
字号:
	fp=global_resources->fopen(filename,"a");#else	fp=fopen(filename,"a");#endif	if(!fp) {		printf("  Report3: Cannot open %s for appending\n",filename);		return;	}	as->report(fp);#ifdef RESERVE_FOPEN_FD	global_resources->fclose(fp);#else	fclose(fp);#endif		printf("  Report3 written to %s\n",filename);}#ifdef USE_FDS// ------------------------- file descriptor servicing ----------------------gateFd::gateFd(const int fdIn,const fdRegType typ,gateServer& s) :	fdReg(fdIn,typ),server(s){#if DEBUG_TIMES && DEBUG_FD	printf("%s gateFd::gateFd: fd=%d count=%d\n",timeStamp(),fdIn,++count);#endif}gateFd::~gateFd(void){	gateDebug0(5,"~gateFd()\n");#if DEBUG_TIMES && DEBUG_FD	printf("%s gateFd::~gateFd: count=%d\n",timeStamp(),--count);#endif}void gateFd::callBack(void){#if DEBUG_TIMES && 0    epicsTime begin(epicsTime::getCurrent());#endif	gateDebug0(51,"gateFd::callback()\n");#if 0	// This causes too many calls to ca_poll, most of which are	// wasted.  Without it, fdManager exits when there is activity on	// a file descriptor.  If file descriptors are not managed	// (USE_FDS not defined), fdManager continues when there is	// activity on a file descriptor	ca_poll();#endif#if DEBUG_TIMES && 0	epicsTime end(epicsTime::getCurrent());	printf("%s gateFd::callBack: pend: %.3f\n",	  timeStamp(),(double)(end-begin));#endif}#endif#ifdef USE_FDS#if DEBUG_TIMESint gateFd::count(0);#endif	#endif	// ----------------------- server methods --------------------gateServer::gateServer(char *prefix ) :	caServer(),#ifdef STAT_PVS	total_vc(0u),	total_pv(0u),	total_alive(0u),	total_active(0u),	total_inactive(0u),	total_unconnected(0u),	total_dead(0u),	total_connecting(0u),	total_disconnected(0u),# ifdef USE_FDS	total_fd(0u),# endif#endif	last_dead_cleanup(time(NULL)),	last_inactive_cleanup(time(NULL)),	last_connect_cleanup(time(NULL)),	last_beacon_time(time(NULL)),	suppressed_refresh_flag(0)	{	gateDebug0(5,"gateServer()\n");	// Initialize channel access#ifdef USE_313	int status=ca_task_initialize();	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::gateServer: ca_task_initialize failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}#else	int status=ca_context_create(ca_disable_preemptive_callback);	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::gateServer: ca_context_create failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}#endif#ifdef USE_FDS	status=ca_add_fd_registration(::fdCB,this);	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::gateServer: ca_add_fd_registration failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}#endif	status=ca_add_exception_event(::exCB,NULL);	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::gateServer: ca_add_exception_event failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}	select_mask|=(alarmEventMask()|valueEventMask()|logEventMask());	alh_mask|=alarmEventMask();	exist_count=0;#if statCount	// Initialize stats	initStats(prefix);#ifdef RATE_STATS	client_event_count=0;	post_event_count=0;	loop_count=0;#endif#ifdef CAS_DIAGNOSTICS#if 0// Jeff did not implement setting counts	setEventsProcessed(0);	setEventsPosted(0);	#endif#endif#endif	setDeadCheckTime();	setInactiveCheckTime();	setConnectCheckTime();}gateServer::~gateServer(void){	gateDebug0(5,"~gateServer()\n");	// remove all PVs from my lists	gateVcData *vc,*old_vc;	gatePvNode *old_pv,*pv_node;	gatePvData *pv;	while((pv_node=pv_list.first()))	{		pv_list.remove(pv_node->getData()->name(),old_pv);		pv=old_pv->getData();     // KE: pv not used?		pv_node->destroy();	}	while((pv_node=pv_con_list.first()))	{		pv_con_list.remove(pv_node->getData()->name(),old_pv);		pv=old_pv->getData();     // KE: pv not used?		pv_node->destroy();	}	while((vc=vc_list.first()))	{		vc_list.remove(vc->name(),old_vc);		vc->markNoList();		delete vc;	}#if statCount	// remove all server stats	for(int i=0; i < statCount; i++) {		if(stat_table[i].pv) {			delete stat_table[i].pv;			stat_table[i].pv=NULL;		}		if(stat_table[i].descPv) {			delete stat_table[i].descPv;			stat_table[i].descPv=NULL;		}	}#endif	int status=ca_flush_io();	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::~gateServer: ca_flush_io failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}#ifdef USE_313	status=ca_task_exit();	if(status != ECA_NORMAL) {	    fprintf(stderr,"%s gateServer::~gateServer: ca_task_exit failed:\n"		  " %s\n",timeStamp(),ca_message(status));	}#else	ca_context_destroy();#endif}void gateServer::checkEvent(void){	gateDebug0(51,"gateServer::checkEvent()\n");	ca_poll();	connectCleanup();	inactiveDeadCleanup();}#ifdef USE_FDSvoid gateServer::fdCB(void* ua, int fd, int opened){	gateServer* s = (gateServer*)ua;	fdReg* reg;	gateDebug3(5,"gateServer::fdCB(gateServer=%p,fd=%d,opened=%d)\n",		ua,fd,opened);	if((opened)) {#ifdef STAT_PVS		s->setStat(statFd,++(s->total_fd));#endif		reg=new gateFd(fd,fdrRead,*s);	} else {#ifdef STAT_PVS		s->setStat(statFd,--(s->total_fd));#endif		gateDebug0(5,"gateServer::fdCB() need to delete gateFd\n");		reg=fileDescriptorManager.lookUpFD(fd,fdrRead);		delete reg;	}}#endifdouble gateServer::delay_quick=.001; // 1 msdouble gateServer::delay_normal=1.0; // 1 secdouble gateServer::delay_current=0;void gateServer::quickDelay(void)   { delay_current=delay_quick; }void gateServer::normalDelay(void)  { delay_current=delay_normal; }double gateServer::currentDelay(void) { return delay_current; }#if HANDLE_EXCEPTIONSvoid gateServer::exCB(EXCEPT_ARGS args)#elsevoid gateServer::exCB(EXCEPT_ARGS /*args*/)#endif{	gateDebug0(9,"exCB: -------------------------------\n");	/*	gateDebug1(9,"exCB: name=%s\n",ca_name(args.chid));	gateDebug1(9,"exCB: type=%d\n",ca_field_type(args.chid));	gateDebug1(9,"exCB: number of elements=%d\n",ca_element_count(args.chid));	gateDebug1(9,"exCB: host name=%s\n",ca_host_name(args.chid));	gateDebug1(9,"exCB: read access=%d\n",ca_read_access(args.chid));	gateDebug1(9,"exCB: write access=%d\n",ca_write_access(args.chid));	gateDebug1(9,"exCB: state=%d\n",ca_state(args.chid));	gateDebug0(9,"exCB: -------------------------------\n");	gateDebug1(9,"exCB: type=%d\n",args.type);	gateDebug1(9,"exCB: count=%d\n",args.count);	gateDebug1(9,"exCB: status=%d\n",args.stat);	*/	// This is the exception callback - log a message about the PV#if HANDLE_EXCEPTIONS	static epicsTime last=epicsTime::getCurrent();	static int nExceptions=0;	static int ended=0;	// Reset counter if EXCEPTION_RESET_TIME has passed since last print	epicsTime cur=epicsTime::getCurrent();	double delta=cur-last;	if(delta > EXCEPTION_RESET_TIME) {		nExceptions=0;		ended=0;	}	// Handle these cases with less output and no limits since they	// are common		// Virtual circuit disconnect	// Virtual circuit unresponsive	if (args.stat == ECA_DISCONN || args.stat == ECA_UNRESPTMO) {		fprintf (stderr, "%s Warning: %s %s \n",				 timeStamp(),				 ca_message(args.stat)?ca_message(args.stat):"<no message>",				 args.ctx?args.ctx:"<no context>");		return;	}	// Check if we have exceeded the limits	if(ended) return;	if(nExceptions++ > MAX_EXCEPTIONS) {	    ended=1;	    fprintf(stderr,"gateServer::exCB: Channel Access Exception:\n"	      "Too many exceptions [%d]\n"	      "No more will be printed for %d seconds\n",	      MAX_EXCEPTIONS,EXCEPTION_RESET_TIME);	    ca_add_exception_event(NULL, NULL);	    return;	}	last=cur;	fprintf(stderr,"%s gateServer::exCB: Channel Access Exception:\n"	  "  Channel Name: %s\n"	  "  Native Type: %s\n"	  "  Native Count: %lu\n"	  "  Access: %s%s\n"	  "  IOC: %s\n"	  "  Message: %s\n"	  "  Context: %s\n"	  "  Requested Type: %s\n"	  "  Requested Count: %ld\n"	  "  Source File: %s\n"	  "  Line number: %u\n",	  timeStamp(),	  args.chid?ca_name(args.chid):"Unavailable",	  args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable",	  args.chid?ca_element_count(args.chid):0,	  args.chid?(ca_read_access(args.chid)?"R":""):"Unavailable",	  args.chid?(ca_write_access(args.chid)?"W":""):"",	  args.chid?ca_host_name(args.chid):"Unavailable",	  ca_message(args.stat)?ca_message(args.stat):"Unavailable",	  args.ctx?args.ctx:"Unavailable",	  dbf_type_to_text(args.type),	  args.count,	  args.pFile?args.pFile:"Unavailable",	  args.pFile?args.lineNo:0);#endif}void gateServer::errlogCB(void * /*userData*/, const char * /*message*/){#if 0	fflush(stderr); fflush(stdout);	// The messages are printed via printf.  This is redundant and	// multiple lines get intermingled.	fprintf(stderr,"\n%s Errlog message:\n%s\nEnd message\n",	  timeStamp(),message);	fflush(stderr); fflush(stdout);#else	fflush(stderr); fflush(stdout);	fprintf(stderr,"\n%s !!! Errlog message received (message is above)\n",	  timeStamp());	fflush(stderr); fflush(stdout);#endif}void gateServer::connectCleanup(void){	gateDebug0(51,"gateServer::connectCleanup()\n");	gatePvData* pv;	if(global_resources->connectTimeout()>0 && 	   timeConnectCleanup()<global_resources->connectTimeout())		return;#if DEBUG_PV_CON_LIST	unsigned long pos=1;	unsigned long total=pv_con_list.count();#endif	#if DEBUG_PV_CONNNECT_CLEANUP 	printf("\ngateServer::connectCleanup: "	  "timeConnectCleanup=%ld timeDeadCheck=%ld\n"	  "  timeInactiveCheck=%ld elapsedTime=%ld\n",	  timeConnectCleanup(),timeDeadCheck(),	  timeInactiveCheck(),time(NULL)-start_time);	printf("  pv_list.count()=%d pv_con_list.count()=%d\n",	  pv_list.count(),pv_con_list.count());#endif	tsDLIter<gatePvNode> iter=pv_con_list.firstIter();	gatePvNode *pNode;	while(iter.valid())	{		tsDLIter<gatePvNode> tmpIter = iter;		tmpIter++;		pNode=iter.pointer();		pv=pNode->getData();#if DEBUG_PV_CON_LIST		printf("  Node %ld: name=%s\n"		  "  timeConnecting=%ld totalElements=%d getStateName=%s\n",		  pos,		  pv->name(),pv->timeConnecting(),pv->totalElements(),		  pv->getStateName());		printf("Pointers: iter=%x tmpIter=0x%x\n",		  iter.pointer(),tmpIter.pointer());#endif		if(pv->timeConnecting()>=global_resources->connectTimeout())		{			gateDebug1(3,"gateServer::connectCleanup() "			  "cleaning up PV %s\n",pv->name());			// clean from connecting list#if DEBUG_PV_CON_LIST			printf("  Removing node (0x%x) %ld of %ld [%lu|%lu|%lu,%lu|%lu,%lu,%lu]: name=%s\n"			  "  timeConnecting=%ld totalElements=%d getStateName=%s\n",			  pNode,pos,total,			  total_vc,total_pv,total_active,total_inactive,			  total_connecting,total_dead,total_disconnected,			  pv->name(),			  pv->timeConnecting(),pv->totalElements(),pv->getStateName());#endif			int status = pv_con_list.remove(pv->name(),pNode);			if(status) printf("%s Clean from connecting PV list failed for pvname=%s.\n",				timeStamp(),pv->name());			delete pNode;			if(pv->pendingConnect()) pv->death();		}		iter=tmpIter;#if DEBUG_PV_CON_LIST		pos++;		printf("New pointers: iter=%x tmpIter=0x%x\n",		  iter.pointer(),tmpIter.pointer());#endif	}#if DEBUG_PV_CON_LIST	printf("gateServer::connectCleanup: After: \n"	  "  pv_list.count()=%d pv_con_list.count()=%d\n",	  pv_list.count(),pv_con_list.count());#endif	setConnectCheckTime();}void gateServer::inactiveDeadCleanup(void){	gateDebug0(51,"gateServer::inactiveDeadCleanup()\n");	gatePvData *pv;	int dead_check=0,inactive_check=0;	// Only do the checks if the smallest of the timeout intervals	// (usually the dead timeout) has passed since the last check	if(timeDeadCheck() >= global_resources->deadTimeout())		dead_check=1;	if(timeInactiveCheck() >= global_resources->inactiveTimeout())		inactive_check=1;	if(dead_check==0 && inactive_check==0) return;#if DEBUG_PV_LIST	int ifirst=1;#endif	tsDLIter<gatePvNode> iter=pv_list.firstIter();	gatePvNode *pNode;	while(iter.valid())	{		tsDLIter<gatePvNode> tmpIter = iter;		tmpIter++;		pNode=iter.pointer();		pv=pNode->getData();		if(pv->dead() &&		  pv->timeDead()>=global_resources->deadTimeout())		{			gateDebug1(3,"gateServer::inactiveDeadCleanup() dead PV %s\n",				pv->name());			int status=pv_list.remove(pv->name(),pNode);#if DEBUG_PV_LIST			if(ifirst) {			    ifirst=0;			}			printf("%s gateServer::inactiveDeadCleanup(dead): [%lu|%lu|%lu,%lu|%lu,%lu,%lu]: "			  "name=%s time=%ld count=%d state=%s\n",			  timeStamp(),			  total_vc,total_pv,total_active,total_inactive,			  total_connecting,total_dead,total_disconnected,			  pv->name(),pv->timeDead(),pv->totalElements(),pv->getStateName());#endif			if(status) printf("%s Clean dead PV from PV list failed for pvname=%s.\n",				timeStamp(),pv->name());			pNode->destroy();		}		else if(pv->inactive() &&		  pv->timeInactive()>=global_resources->inactiveTimeout())		{			gateDebug1(3,"gateServer::inactiveDeadCleanup inactive PV %s\n",				pv->name());

⌨️ 快捷键说明

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