📄 gateserver.cc
字号:
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 + -