diff --git a/src/cas/example/testdb/Makefile b/src/cas/example/testdb/Makefile new file mode 100644 index 000000000..d2a6e1302 --- /dev/null +++ b/src/cas/example/testdb/Makefile @@ -0,0 +1,7 @@ + +TOP=../../../.. + +include $(TOP)/config/CONFIG_BASE + +include $(TOP)/config/RULES_ARCHS + diff --git a/src/cas/example/testdb/Makefile.Host b/src/cas/example/testdb/Makefile.Host new file mode 100644 index 000000000..0045a95db --- /dev/null +++ b/src/cas/example/testdb/Makefile.Host @@ -0,0 +1,21 @@ + +CAS = ../../.. +TOP = $(CAS)/../.. + +include $(TOP)/config/CONFIG_BASE + +CXXCMPLR = STRICT + +PROD_LIBS := cas ca gdd Com + +SRCS += pvServ.cc + +PROD :=pvServ + +include $(TOP)/config/RULES.Host + +clean:: + @$(RM) pvServ + @$(RM) -rf Templates.DB + @$(RM) core + diff --git a/src/cas/example/testdb/pvServ.cc b/src/cas/example/testdb/pvServ.cc new file mode 100644 index 000000000..fe2abce0d --- /dev/null +++ b/src/cas/example/testdb/pvServ.cc @@ -0,0 +1,276 @@ + +#include +#include "pvServ.h" +#include "fdManager.h" +#include "gdd.h" +#include "gddAppTable.h" +#include "alarm.h" + +static int appValue; + +void dBase::eventReady(void) +{ + if(counter+1.0 > 100.0) + writeData(0.0); + else + writeData(counter+1.0); +} + +void dBase::writeData(double x) +{ + counter=x; + time((time_t*)&ts.tv_sec); + + if(counter>hihi) + { sevr=MAJOR_ALARM; stat=HIHI_ALARM; } + else if(counterhigh) + { sevr=MINOR_ALARM; stat=HIGH_ALARM; } + else if(countereventReady(); +} + +int main(int argc, char* argv[]) +{ + gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable(); + int rc; + int total_pv; + double rate; + serv* server; + char* name; + + if(argc<3) + { + fprintf(stderr,"Usage %s pv_total monitor_rate optional_pv_prefix\n", + argv[0]); + fprintf(stderr," pv_total is the number of PVs to generate (int)\n"); + fprintf(stderr," monitor_rate is events per second (float)\n"); + fprintf(stderr," optional_pv_prefix defaults to your login name\n"); + fprintf(stderr,"\n"); + fprintf(stderr," PVs are named _#\n"); + fprintf(stderr," where # is an integer is the range [0,pv_total)\n"); + + return -1; + } + + if(sscanf(argv[1],"%d",&total_pv)!=1) + { + fprintf(stderr,"Failed to convert pv_total argument to number\n"); + return -1; + } + if(sscanf(argv[2],"%lf",&rate)!=1) + { + fprintf(stderr,"Failed to convert monitor_rate argument to number\n"); + return -1; + } + if(argc<=4) + name=argv[3]; + else + name=NULL; + + appValue=table.getApplicationType("value"); + + Debug3("total=%d,rate=%lf,prefix=%s\n",total_pv,rate,name); + + server = new serv(total_pv,rate,name,40u,total_pv,total_pv); + rc=server->Main(); + delete server; + return rc; +} + +int serv::InitDB(void) +{ + unsigned i; + + db_sync=new dBase[pv_total]; + + for(i=0;i= sec && + tv_curr.tv_usec-tv_prev.tv_usec >= (nsec/1000)) + { + for(i=0;i=0 && valpvname): + pvExistReturn(rc); +} + +casPV* serv::createPV(const casCtx& in,const char* pvname) +{ + casPV* rc=NULL; + int val; + + Debug1("createPV: %s\n",pvname); + + if(strncmp(pvname,prefix,prefix_len)==0) + { + // we may have this one, number is after underscore + if(sscanf(&pvname[prefix_len+1],"%d",&val)==1) + { + Debug("createPV: I am making this PV\n"); + if(val>=0 && valunreference(); + db.node=NULL; +} + +unsigned servPV::maxSimultAsyncOps(void) const { return 100000u; } + +caStatus servPV::interestRegister() +{ + if(!monitored) monitored=1; + return S_casApp_success; +} + +void servPV::interestDelete() +{ + if(monitored) monitored=0; +} + +aitEnum servPV::bestExternalType() const +{ + return aitEnumFloat64; +} + +caStatus servPV::read(const casCtx&, gdd &dd) +{ + Debug1("read: %s\n",db.pvname); + gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable(); + + // this is a cheesy way to do this + value->put(db.counter); + value->setStatSevr(db.stat,db.sevr); + value->setTimeStamp(&db.ts); + + table.smartCopy(&dd,value); + return S_casApp_success; +} + +caStatus servPV::write(const casCtx&, gdd &dd) +{ + Debug1("write: %s\n",db.pvname); + gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable(); + + // this is also cheesy + table.smartCopy(value,&dd); + db.writeData((double)*value); + return S_casApp_success; +} + +void servPV::destroy() +{ + casPV::destroy(); +} + +void servPV::eventReady(void) +{ + value->put(db.counter); + value->setStatSevr(db.stat,db.sevr); + value->setTimeStamp(&db.ts); + postEvent(mgr.event_mask,*value); +} + diff --git a/src/cas/example/testdb/pvServ.h b/src/cas/example/testdb/pvServ.h new file mode 100644 index 000000000..8dd6b1fdf --- /dev/null +++ b/src/cas/example/testdb/pvServ.h @@ -0,0 +1,87 @@ + +#include "casdef.h" +#include "osiTimer.h" + +class gdd; +class servPV; + +#ifdef PVDEBUG +#define Debug(str) { fprintf(stderr,str); } +#define Debug1(str,val) { fprintf(stderr,str,val); } +#define Debug2(str,val1,val2) { fprintf(stderr,str,val1,val2); } +#define Debug3(str,val1,val2,val3) { fprintf(stderr,str,val1,val2,val3); } +#else +#define Debug(str) ; +#define Debug1(str,val) ; +#define Debug2(str,val1,val2) ; +#define Debug3(str,val1,val2,val3) ; +#endif + +class dBase +{ +public: + dBase(void) + { + pvname[0]='\0';counter=0; + hihi=90.0;high=80.0;low=20.0;lolo=10.0; + ts.tv_sec=0; ts.tv_nsec=0; + stat=0; sevr=0; + node=NULL; + } + + void eventReady(void); + void writeData(double); + + char pvname[50]; + double counter; + double hihi,high,low,lolo; + aitTimeStamp ts; + aitInt16 stat,sevr; + servPV* node; +}; + +class serv : public caServer +{ +public: + serv(int totpv,double rate,char* prefix, + unsigned maxnamelen,unsigned pvtotalest, unsigned maxsimio); + virtual ~serv(void); + + virtual pvExistReturn pvExistTest(const casCtx& c,const char* pvname); + virtual casPV* createPV(const casCtx& c,const char* pvname); + + int InitDB(void); + int Main(void); + + // sloppy + char* prefix; + int prefix_len; + int pv_total; + double event_rate; + casEventMask event_mask; + dBase* db_sync; +}; + +class servPV : public casPV +{ +public: + servPV(const casCtx&,serv&,const char* pvname,dBase&); + virtual ~servPV(void); + + virtual caStatus interestRegister(void); + virtual void interestDelete(void); + virtual aitEnum bestExternalType(void) const; + virtual caStatus read(const casCtx &ctx, gdd &prototype); + virtual caStatus write(const casCtx &ctx, gdd &value); + virtual void destroy(void); + virtual unsigned maxSimultAsyncOps(void) const; + + void eventReady(void); + +private: + serv& mgr; + dBase& db; + gdd* value; + int monitored; +}; +