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

📄 gateserver.cc

📁 EPICS CA gateway, base on channel access protocol
💻 CC
📖 第 1 页 / 共 5 页
字号:
/*************************************************************************\* Copyright (c) 2002 The University of Chicago, as Operator of Argonne* National Laboratory.* Copyright (c) 2002 Berliner Speicherring-Gesellschaft fuer Synchrotron-* Strahlung mbH (BESSY).* Copyright (c) 2002 The Regents of the University of California, as* Operator of Los Alamos National Laboratory.* This file is distributed subject to a Software License Agreement found* in the file LICENSE that is included with this distribution. \*************************************************************************//*+********************************************************************* * * File:       gateServer.cc * Project:    CA Proxy Gateway * * Descr.:     Gateway server class *             - Provides the CAS virtual interface *             - Manages Gateway lists and hashes, cleanup *             - Server statistics variables * * Author(s):  J. Kowalkowski, J. Anderson, K. Evans (APS) *             R. Lange (BESSY) * *********************************************************************-*/#define DEBUG_FD 0#define DEBUG_SET_STAT 0#define DEBUG_PV_CON_LIST 0#define DEBUG_PV_LIST 0#define DEBUG_PV_CONNNECT_CLEANUP 0#define DEBUG_EXIST 0#define DEBUG_DELAY 0#define DEBUG_CLOCK 0#define DEBUG_ACCESS 0#define DEBUG_DESC 0#define DEBUG_FDMGR 0#define DEBUG_HISTORY 0#if DEBUG_HISTORY# define HISTNAME "GW:432:S05"# define HISTNUM 10#endif#ifdef __linux__#undef USE_LINUX_PROC_FOR_CPU#endif// DEBUG_TIMES prints a message every minute, which helps determine// when things happen.#define DEBUG_TIMES 0// This is the interval used with DEBUG_TIMES#define GATE_TIME_STAT_INTERVAL 60 /* sec */// This causes traces to be printed when exceptions occur.  It// requires Base 3.15.#define DEBUG_EXCEPTION 0// Print only MAX_EXCEPTIONS exceptions unless EXCEPTION_RESET_TIME// has passed since the last one printed#define MAX_EXCEPTIONS 100#define EXCEPTION_RESET_TIME 3600  /* sec */// Interval for rate statistics in seconds#define RATE_STATS_INTERVAL 10u// Number of load elements to get in getloadavg.  Should be 1, unless// the implementation in the Gateway is changed.#define N_LOAD 1#define ULONG_DIFF(n1,n2) (((n1) >= (n2))?((n1)-(n2)):((n1)+(ULONG_MAX-(n2))))#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifdef SOLARIS// Is in stdlib.h elsewhere, not available on WIN32#include <sys/loadavg.h>#endif#ifdef WIN32#else# include <unistd.h>#endif#include <gdd.h>#if DEBUG_EXCEPTION#include <epicsThrowTrace.h>#endif#include "gateResources.h"#include "gateServer.h"#include "gateAs.h"#include "gateVc.h"#include "gatePv.h"#include "gateStat.h"#ifdef __linux__# ifdef USE_LINUX_PROC_FOR_CPUstatic double linuxCpuTimeDiff(void);static pid_t gate_pid=0;# endifstatic clock_t mainClock=(clock_t)(-1);#endif// extern "C" wrappers needed by CA routines for callbacksextern "C" {#ifdef USE_FDS    // file descriptor callback	static void fdCB(void* ua, int fd, int opened) {		gateServer::fdCB(ua, fd, opened);	}#endif	// exception callback	static void exCB(EXCEPT_ARGS args) {		gateServer::exCB(args);	}	// errlog listener callback	static void errlogCB(void *userData, const char *message) {		gateServer::errlogCB(userData,message);	}}// ---------------------------- general main processing function -------------#ifndef WIN32extern "C" {typedef void (*SigFunc)(int);static SigFunc save_usr1=NULL;static SigFunc save_usr2=NULL;static void sig_pipe(int){	fprintf(stderr,"Got SIGPIPE interrupt!");	signal(SIGPIPE,sig_pipe);}static void sig_usr1(int x){	// Call a class function to get access to class variables	gateServer::sig_usr1(x);}static void sig_usr2(int x){	// Call a class function to get access to class variables	gateServer::sig_usr2(x);}} //extern "C"#endif// Static initializations// KE: Volatile because they can be set in signal handlers?volatile unsigned long gateServer::command_flag = 0;volatile unsigned long gateServer::report1_flag = 0;volatile unsigned long gateServer::report2_flag = 0;volatile unsigned long gateServer::report3_flag = 0;volatile unsigned long gateServer::newAs_flag = 0;volatile unsigned long gateServer::quit_flag = 0;volatile unsigned long gateServer::quitserver_flag = 0;void gateServer::mainLoop(void){	int not_done=1;	// KE: ca_poll should be called every 100 ms	// fdManager::process can block in select for delay time	// so delay must be less than 100 ms to insure ca_poll gets called	// if delay = 0.0 select will not block)	double delay=.010; // (10 ms)	printf("Statistics PV prefix is %s\n",stat_prefix);	// Print if too many have been started recently	printRecentHistory();#if DEBUG_TIMES	epicsTime begin, end, lastPrintTime;	double fdTime, pendTime, cleanTime;	unsigned long nLoops=0;	printf("%s gateServer::mainLoop: Starting and printing statistics every %d seconds\n",	  timeStamp(),GATE_TIME_STAT_INTERVAL);    printf("  Key: [VcTotal|PvTotal|Active,Inactive|Connecting,Dead,Disconnected]\n");#endif#if DEBUG_EXCEPTION	epicsThrowTraceEnable = true;#endif	// Establish an errorLog listener	errlogAddListener(::errlogCB,NULL);	// This should create as since this is the first call to getAs()	as=global_resources->getAs();	if(!as) {		printf("%s gateServer::mainLoop: Failed to set up access security\n",		  timeStamp());		exit(-1);	}	gateAsCa();	// as->report(stdout);#ifndef WIN32	save_usr1=signal(SIGUSR1,::sig_usr1);	save_usr2=signal(SIGUSR2,::sig_usr2);#if 0	// KE: This should be handled in both CA and CAS now using	// osiSigPipeIgnore. There is no sigignore on Linux, so use	// osiSigPipeIgnore if it has to be implemented here.	SigFunc old=signal(SIGPIPE,sig_pipe);	sigignore(SIGPIPE);#endif#endif	time(&start_time);	markNoRefreshSuppressed();#ifdef USE_LINUX_PROC_FOR_CPU	// Save the pid.  Could put this in a class variable.	gate_pid=getpid();	if(!gate_pid) printf("gateServer::mainLoop: Could not get pid\n");	else printf("gateServer::mainLoop: gate_pid=%d\n",gate_pid);#endif	// Initialize stat counters#if defined(RATE_STATS) || defined(CAS_DIAGNOSTICS)	// Start a default timer queue (true to use shared queue, false to	// have a private one)	epicsTimerQueueActive &queue = 	  epicsTimerQueueActive::allocate(true);	gateRateStatsTimer *statTimer = new gateRateStatsTimer(queue,	  RATE_STATS_INTERVAL, this);	if(statTimer) {	  // Call the expire routine to initialize it	    statTimer->expire(epicsTime::getCurrent());	  // Then start the timer	    statTimer->start();	} else {	    printf("gateServer::mainLoop: Could not start statistics timer\n");	}#endif#if DEBUG_TIMES	lastPrintTime=epicsTime::getCurrent();	fdTime=0.0;	pendTime=0.0;	cleanTime=0.0;#endif	// Main loop	while(not_done)	{#if defined(RATE_STATS) || defined(CAS_DIAGNOSTICS)		loop_count++;#endif#if DEBUG_TIMES		nLoops++;		begin=epicsTime::getCurrent();#endif		// Process		fileDescriptorManager.process(delay);#if DEBUG_TIMES		end=epicsTime::getCurrent();		fdTime+=(end-begin);		begin=end;#endif		// Poll		//  KE: used to be checkEvent();		ca_poll();#if DEBUG_TIMES		end=epicsTime::getCurrent();		pendTime+=(end-begin);		begin=end;#endif		// Cleanup		connectCleanup();		inactiveDeadCleanup();#if DEBUG_TIMES		end=epicsTime::getCurrent();		cleanTime+=(end-begin);		if((end-lastPrintTime) > GATE_TIME_STAT_INTERVAL) {#ifdef STAT_PVS			printf("%s gateServer::mainLoop: [%lu|%lu|%lu,%lu|%lu,%lu,%lu] "			  "loops: %lu process: %.3f pend: %.3f clean: %.3f\n",			  timeStamp(),			  total_vc,total_pv,total_active,total_inactive,			  total_connecting,total_dead,total_disconnected,			  nLoops,			  fdTime/(double)nLoops,			  pendTime/(double)nLoops,			  cleanTime/(double)nLoops);#else			printf("%s gateServer::mainLoop: "			  "loops: %lu process: %.3f pend: %.3f clean: %.3f\n",			  timeStamp(),			  nLoops,			  fdTime/(double)nLoops,			  pendTime/(double)nLoops,			  cleanTime/(double)nLoops);#endif			nLoops=0;			lastPrintTime=epicsTime::getCurrent();			fdTime=0.0;			pendTime=0.0;			cleanTime=0.0;		}#endif				// Make sure messages get out		fflush(stderr); fflush(stdout);		// Do flagged reports		if(command_flag) {			gateCommands(global_resources->commandFile());			command_flag=0;			setStat(statCommandFlag,0ul);		}		if(report1_flag) {			report1();			report1_flag=0;			setStat(statReport1Flag,0ul);		}		if(report2_flag) {			report2();			report2_flag=0;			setStat(statReport2Flag,0ul);		}		if(report3_flag) {			report3();			report3_flag=0;			setStat(statReport3Flag,0ul);		}		if(newAs_flag) {			printf("%s Reading access security files\n",timeStamp());			newAs();			newAs_flag=0;			setStat(statNewAsFlag,0ul);		}		if(quit_flag) {			if(quit_flag == 1) {				printf("%s Stopping (quitFlag was set to 1)\n",timeStamp());				fflush(stderr); fflush(stdout);			}			quit_flag=0;			setStat(statQuitFlag,0ul);			// return here will delete gateServer			return;		}		if(quitserver_flag) {			printf("%s Stopping server (quitServerFlag was set to 1)\n",			  timeStamp());			quitserver_flag=0;			setStat(statQuitServerFlag,0ul);			if(global_resources->getServerMode()) {				// Has a server#ifndef WIN32				pid_t parentPid=getppid();				if(parentPid >= 0) {					kill(parentPid,SIGTERM);				} else {					exit(0);				}#endif							} else {				// Doesn't have a server, just quit				exit(0);			}		}#ifdef __linux__# ifndef USE_LINUX_PROC_FOR_CPU		// Get clock for this thread		mainClock=clock();# endif#endif	}}// This is a wrapper around caServer::generateBeaconAnomaly.  Generate// a beacon anomaly as long as the time since the last one exceeds the// reconnect inhibit time.  (The server may also prevent too frequent// beacon anomalies.)  If it is not generated, mark it as suppressed,// but suppressed is not currently used.  Note that one beacon anomaly// causes the clients to reissue search request sequences consisting// of 100 searches over a period of about 8 min.  It is not necessary// to generate beacon anomalies much more frequently than this.void gateServer::generateBeaconAnomaly (){	if(timeSinceLastBeacon() >= global_resources->reconnectInhibit()) {		caServer::generateBeaconAnomaly();		setFirstReconnectTime();		markNoRefreshSuppressed();	} else {		// KE: Not used		markRefreshSuppressed();	}}void gateServer::gateCommands(const char* cfile){	FILE* fp;	char inbuf[200];	char *cmd,*ptr;	int r1Flag=0,r2Flag=0,r3Flag=0,asFlag=0;	if(cfile) {		printf("%s Reading command file: %s\n",timeStamp(),cfile);		errno=0;#ifdef RESERVE_FOPEN_FD		fp=global_resources->fopen(cfile,"r");#else		fp=fopen(cfile,"r");#endif		if(fp == NULL)	{			fprintf(stderr,"%s Failed to open command file: %s\n",			  timeStamp(),cfile);			fflush(stderr);			perror("Reason");			fflush(stderr);			return;		}	} else {		return;	}	while(fgets(inbuf,sizeof(inbuf),fp)) {		if((ptr=strchr(inbuf,'#'))) *ptr='\0';		cmd=strtok(inbuf," \t\n");		while(cmd) {			if(strcmp(cmd,"R1")==0) r1Flag=1;			else if(strcmp(cmd,"R2")==0) r2Flag=1;			else if(strcmp(cmd,"R3")==0) r3Flag=1;			else if(strcmp(cmd,"AS")==0) asFlag=1;			else {				printf("  Invalid command %s\n",cmd);				fflush(stdout);			}			cmd=strtok(NULL," \t\n");		}	}	// Free the reserved file descriptor before we read access	// security or write reports#ifdef RESERVE_FOPEN_FD	global_resources->fclose(fp);#else	fclose(fp);#endif	// Now do the commands	if(r1Flag) {		report1();		fflush(stdout);	}	if(r2Flag) {		report2();		fflush(stdout);	}	if(asFlag) {		printf("%s Reading access security files\n",timeStamp());		newAs();			fflush(stdout);	}	// Do the report after the new access security	if(r3Flag) {		report3();		fflush(stdout);	}		return;}// We rely on CAS being non-threaded and CAC not calling our callbacks// while this routine completes, otherwise it should be lockedvoid gateServer::newAs(void)

⌨️ 快捷键说明

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