📄 gatepv.cc
字号:
/*************************************************************************\* 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: gatePv.cc * Project: CA Proxy Gateway * * Descr.: PV = Client side (lower half) of Proxy Gateway Channel * Handles all CAC related stuff: * - Connections (and exception handling) * - Monitors (value and ALH data) * - Put operations (Gets are answered by the VC) * * Author(s): J. Kowalkowski, J. Anderson, K. Evans (APS) * R. Lange (BESSY) * *********************************************************************-*/#define DEBUG_TOTAL_PV 0#define DEBUG_PV_CON_LIST 0#define DEBUG_PV_LIST 0#define DEBUG_VC_DELETE 0#define DEBUG_GDD 0#define DEBUG_PUT 0#define DEBUG_BEAM 0#define DEBUG_ENUM 0#define DEBUG_DELAY 0#define DEBUG_SLIDER 0#define DEBUG_HISTORY 0#if DEBUG_HISTORY# define HISTNAME "GW:432:S05"# define HISTNUM 10#endif#define OMIT_CHECK_EVENT 1#include <stdio.h>#include <string.h>#include <fcntl.h>#include <time.h>#include <sys/types.h>#ifdef WIN32#else# include <unistd.h># include <sys/time.h>#endif#include "tsDLList.h"#include <gdd.h>#include <gddApps.h>#include <gddAppTable.h>#include <dbMapper.h>#include "gateResources.h"#include "gateServer.h"#include "gatePv.h"#include "gateVc.h"#include "gateAs.h"// extern "C" wrappers needed by CA routines for callbacksextern "C" { extern void connectCB(CONNECT_ARGS args) { // connection callback gatePvData::connectCB(args); } extern void accessCB(ACCESS_ARGS args) { // access security callback gatePvData::accessCB(args); } extern void eventCB(EVENT_ARGS args) { // value-changed callback gatePvData::eventCB(args); } extern void alhCB(EVENT_ARGS args) { // alh info value-changed callback gatePvData::alhCB(args); } extern void putCB(EVENT_ARGS args) { // put callback gatePvData::putCB(args); } extern void getCB(EVENT_ARGS args) { // get callback gatePvData::getCB(args); }}// quick access to global_resources#define GR global_resources#define GETDD(ap) gddApplicationTypeTable::AppTable().getDD(GR->ap)const char* const gatePvData::pv_state_names[] = { "dead", "inactive", "active", "connecting", "disconnected" };// ------------------------- gdd destructors --------------------------------// Apart from the FixedString destructor, which is definitely needed,// these are probably not necessary. The default gddDestructor does// delete [] (aitUint8 *)v. (aitUint=char) Since delete calls free,// which casts the pointer to a char * anyway, our specific casts are// probably wasted.// Fixed Stringclass gateFixedStringDestruct : public gddDestructor{public: gateFixedStringDestruct(void) { } void run(void *v) { delete [] (aitFixedString *)v; }};// Enumclass gateEnumDestruct : public gddDestructor{public: gateEnumDestruct(void) { } void run(void *v) { delete [] (aitEnum16 *)v; }};// Intclass gateIntDestruct : public gddDestructor{public: gateIntDestruct(void) { } void run(void *v) { delete [] (aitInt32 *)v; }};// Char (Default would also work here)class gateCharDestruct : public gddDestructor{public: gateCharDestruct(void) { } void run(void *v) { delete [] (aitInt8 *)v; }};// Floatclass gateFloatDestruct : public gddDestructor{public: gateFloatDestruct(void) { } void run(void *v) { delete [] (aitFloat32 *)v; }};// Doubleclass gateDoubleDestruct : public gddDestructor{public: gateDoubleDestruct(void) { } void run(void *v) { delete [] (aitFloat64 *)v; }};// Shortclass gateShortDestruct : public gddDestructor{public: gateShortDestruct(void) { } void run(void *v) { delete [] (aitInt16 *)v; }};// ------------------------- pv data methods ------------------------gatePvData::gatePvData(gateServer* m,gateAsEntry* pase,const char* name){ gateDebug2(5,"gatePvData(gateServer=%p,name=%s)\n",(void *)m,name); initClear(); init(m,pase,name);#ifdef STAT_PVS mrg->setStat(statPvTotal,++mrg->total_pv);#endif#if DEBUG_TOTAL_PV printf("gatePvdata: name=%s total_pv=%ld total_alive=%ld\n", name,mrg->total_pv,mrg->total_alive);#endif#if DEBUG_HISTORY if(!strncmp(HISTNAME,name,HISTNUM)) { printf("%s gatePvData::gatePvData: %s state=%s\n",timeStamp(),name, getStateName()); }#endif}gatePvData::~gatePvData(void){ gateDebug1(5,"~gatePvData() name=%s\n",name());#ifdef STAT_PVS switch(getState()) { case gatePvDisconnect: mrg->setStat(statDisconnected,--mrg->total_disconnected); mrg->setStat(statUnconnected,--mrg->total_unconnected); break; case gatePvDead: mrg->setStat(statDead,--mrg->total_dead); mrg->setStat(statUnconnected,--mrg->total_unconnected); break; case gatePvConnect: mrg->setStat(statConnecting,--mrg->total_connecting); mrg->setStat(statUnconnected,--mrg->total_unconnected); break; case gatePvActive: mrg->setStat(statActive,--mrg->total_active); mrg->setStat(statAlive,--mrg->total_alive); break; case gatePvInactive: mrg->setStat(statInactive,--mrg->total_inactive); mrg->setStat(statAlive,--mrg->total_alive); break; } mrg->setStat(statPvTotal,--mrg->total_pv);#endif#if DEBUG_TOTAL_PV printf("~gatePvdata: name=%s total_pv=%ld total_alive=%ld\n", name(),mrg->total_pv),mrg->total_alive;#endif if(vc) { delete vc; vc=NULL; } unmonitor(); alhUnmonitor(); status=ca_clear_channel(chID); if(status != ECA_NORMAL) { fprintf(stderr,"%s ~gatePvData: ca_clear_channel failed for %s:\n" " %s\n", timeStamp(), name()?name():"Unknown",ca_message(status)); } delete [] pv_name; // Clear the callback_list; gatePvCallbackId *id = NULL; while((id=callback_list.first())) { callback_list.remove(*id); delete id; } // Clear the async exist test list gateAsyncE* asynce = NULL; while((asynce=eio.first())) { asynce->removeFromQueue(); }}void gatePvData::initClear(void){ setVC(NULL); status=0; markNotMonitored(); markNoGetPending(); markAlhNotMonitored(); markAlhNoGetPending(); markNoAbort(); markAddRemoveNotNeeded();}void gatePvData::init(gateServer* m,gateAsEntry* pase, const char* name){ gateDebug2(5,"gatePvData::init(gateServer=%p,name=%s)\n",(void *)m,name); gateDebug1(5,"gatePvData::init entry pattern=%s)\n",pase->pattern); mrg=m; asentry=pase; setTimes(); status=0; pv_name=strDup(name); if(asentry==NULL) status=-1; else {#ifdef USE_313 status=ca_search_and_connect(pv_name,&chID,::connectCB,this);#else status=ca_create_channel(pv_name,::connectCB,this, CA_PRIORITY_DEFAULT,&chID);#endif if(status != ECA_NORMAL) { fprintf(stderr,"gatePvData::init: ca_search_and_connect for %s:\n" " %s\n", this->name()?this->name():"Unknown",ca_message(status)); } } if(status==ECA_NORMAL) { status=ca_replace_access_rights_event(chID,::accessCB); setState(gatePvConnect);#ifdef STAT_PVS mrg->setStat(statConnecting,++mrg->total_connecting); mrg->setStat(statUnconnected,++mrg->total_unconnected);#endif if(status==ECA_NORMAL) status=0; else status=-1; } else { gateDebug0(5,"gatePvData::init() search and connect failed!\n"); setState(gatePvDead);#ifdef STAT_PVS mrg->setStat(statDead,++mrg->total_dead); mrg->setStat(statUnconnected,++mrg->total_unconnected);#endif status=-1; } if(status) { // what do I do here? Nothing for now, let creator fix trouble } else { // Put PV into connecting list status = mrg->conAdd(pv_name,*this); if(status) fprintf(stderr,"%s Put into connecting list failed for %s\n", timeStamp(),pv_name);#if DEBUG_PV_CON_LIST printf("%s gatePvData::init: [%lu|%lu|%lu,%lu|%lu,%lu,%lu]: name=%s\n", timeStamp(), mrg->total_vc,mrg->total_pv,mrg->total_active,mrg->total_inactive, mrg->total_connecting,mrg->total_dead,mrg->total_disconnected,#endif } #if OMIT_CHECK_EVENT#else checkEvent(); // do ca_pend_event#endif}aitEnum gatePvData::nativeType(void) const{ return gddDbrToAit[fieldType()].type;}int gatePvData::activate(gateVcData* vcd){ gateDebug2(5,"gatePvData::activate(gateVcData=%p) name=%s\n", (void *)vcd,name()); int rc=-1; #if DEBUG_DELAY if(!strncmp("Xorbit",name(),6)) { printf("%s gatePvData::activate: %s state=%d\n",timeStamp(),name(), getState()); }#endif#if DEBUG_HISTORY if(!strncmp(HISTNAME,name(),HISTNUM)) { printf("%s gatePvData::activate: %s state=%s\n",timeStamp(),name(), getStateName()); }#endif switch(getState()) { case gatePvInactive: gateDebug1(10,"gatePvData::activate() %s PV\n",getStateName()); markAddRemoveNeeded(); vc=vcd; setState(gatePvActive);#ifdef STAT_PVS mrg->setStat(statActive,++mrg->total_active); mrg->setStat(statInactive,--mrg->total_inactive);#endif setActiveTime(); vc->setReadAccess(ca_read_access(chID)?aitTrue:aitFalse); vc->setWriteAccess(ca_write_access(chID)?aitTrue:aitFalse); if(ca_read_access(chID)) rc=get(); else rc=0; break; case gatePvDisconnect: case gatePvDead: gateDebug1(3,"gatePvData::activate() %s PV ?\n",getStateName()); vc=NULL; // NOTE: be sure vc does not respond break; case gatePvActive: gateDebug1(2,"gatePvData::activate() %s PV ?\n",getStateName()); break; case gatePvConnect: // already pending, just return gateDebug1(3,"gatePvData::activate() %s PV ?\n",getStateName()); markAddRemoveNeeded(); break; } return rc;}int gatePvData::deactivate(void){ gateDebug1(5,"gatePvData::deactivate() name=%s\n",name());#if DEBUG_VC_DELETE printf("gatePvData::deactivate: %s\n",name());#endif int rc=0; switch(getState()) { case gatePvActive: gateDebug1(10,"gatePvData::deactivate() %s PV\n",getStateName()); unmonitor(); alhUnmonitor(); setState(gatePvInactive);#ifdef STAT_PVS mrg->setStat(statActive,--mrg->total_active); mrg->setStat(statInactive,++mrg->total_inactive);#endif vc=NULL; setInactiveTime(); break; case gatePvConnect: // delete from the connect pending list gateDebug1(10,"gatePvData::deactivate() %s PV ?\n",getStateName()); markAddRemoveNotNeeded(); vc=NULL; break; default: gateDebug1(3,"gatePvData::deactivate() %s PV ?\n",getStateName()); rc=-1; break; } return rc;}// Called in the connectCB if ca_state is cs_connint gatePvData::life(void){ int rc=0; event_count=0; gateDebug1(5,"gatePvData::life() name=%s\n",name());#if DEBUG_DELAY if(!strncmp("Xorbit",name(),6)) { printf("%s gatePvData::life: loop_count=%d %s state=%d\n", timeStamp(),mrg->loop_count,name(),getState()); }#endif#if DEBUG_HISTORY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -