From 17ff2420b4622c1703792e3593687c2b4b2de392 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Sat, 2 Nov 1996 00:55:02 +0000 Subject: [PATCH] many improvements --- src/cas/build/multiThread/Makefile.Vx | 60 +- src/cas/build/singleThread/Makefile.Unix | 98 ++-- src/cas/example/Makefile.Unix | 11 +- src/cas/example/exAsyncPV.cc | 28 +- src/cas/example/exPV.cc | 19 +- src/cas/example/exServer.cc | 33 +- src/cas/example/exServer.h | 84 +-- src/cas/example/main.cc | 1 + src/cas/generic/README | 39 +- src/cas/generic/caCommonDef.h | 9 +- src/cas/generic/caServer.cc | 39 +- src/cas/generic/caServerI.cc | 142 ++++- src/cas/generic/caServerIIL.h | 87 ++- src/cas/generic/casAsyncIO.cc | 13 +- src/cas/generic/casAsyncIOI.cc | 149 +++-- src/cas/generic/casAsyncIOIIL.h | 19 +- src/cas/generic/casChanDelEv.cc | 4 + src/cas/generic/casChannelI.cc | 57 +- src/cas/generic/casChannelIIL.h | 17 +- src/cas/generic/casClient.cc | 86 +-- src/cas/generic/casClientIL.h | 12 +- src/cas/generic/casCoreClient.cc | 76 +-- src/cas/generic/casDGClient.cc | 291 +++++++--- src/cas/generic/casEventMask.cc | 87 ++- src/cas/generic/casEventMask.h | 37 +- src/cas/generic/casEventSys.cc | 14 +- src/cas/generic/casEventSysIL.h | 105 ++++ src/cas/generic/casInternal.h | 370 ++++++------ src/cas/generic/casMonEvent.cc | 41 +- src/cas/generic/casMonEventIL.h | 82 +++ src/cas/generic/casMonitor.cc | 4 + src/cas/generic/casMsgIO.cc | 88 ++- src/cas/generic/casPV.cc | 4 + src/cas/generic/casPVI.cc | 57 +- src/cas/generic/casPVIIL.h | 11 +- src/cas/generic/casStrmClient.cc | 275 +++++---- src/cas/generic/casdef.h | 375 +++++++++---- src/cas/generic/inBuf.cc | 60 +- src/cas/generic/outBuf.cc | 85 ++- src/cas/generic/server.h | 684 +++++++++-------------- src/cas/io/bsdSocket/caServerIO.cc | 272 ++++----- src/cas/io/bsdSocket/casDGIO.cc | 373 +----------- src/cas/io/bsdSocket/casIOD.h | 256 ++++++--- src/cas/io/bsdSocket/casStreamIO.cc | 155 ++--- src/cas/os/posix/caServerOS.cc | 116 ---- src/cas/os/posix/casClientOS.h | 131 ----- src/cas/os/posix/casDGOS.cc | 196 ------- src/cas/os/posix/casOSD.h | 113 ---- src/cas/os/posix/casStreamOS.cc | 456 --------------- src/cas/os/posix/osiMutex.h | 18 - src/cas/os/vxWorks/README | 2 +- src/cas/os/vxWorks/casClientOS.h | 5 - src/cas/os/vxWorks/casOSD.h | 58 +- src/cas/os/vxWorks/casStreamOS.cc | 20 +- src/cas/os/vxWorks/osiMutex.h | 113 ---- 55 files changed, 2668 insertions(+), 3369 deletions(-) delete mode 100644 src/cas/os/posix/caServerOS.cc delete mode 100644 src/cas/os/posix/casClientOS.h delete mode 100644 src/cas/os/posix/casDGOS.cc delete mode 100644 src/cas/os/posix/casOSD.h delete mode 100644 src/cas/os/posix/casStreamOS.cc delete mode 100644 src/cas/os/posix/osiMutex.h delete mode 100644 src/cas/os/vxWorks/osiMutex.h diff --git a/src/cas/build/multiThread/Makefile.Vx b/src/cas/build/multiThread/Makefile.Vx index 13bc9b2bd..b376bbe76 100644 --- a/src/cas/build/multiThread/Makefile.Vx +++ b/src/cas/build/multiThread/Makefile.Vx @@ -7,7 +7,7 @@ SRC = $(CAS)/generic CA = $(CAS)/../ca IOSRC = $(CAS)/io/bsdSocket OSSRC = $(CAS)/os/vxWorks -VPATH = $(SRC) $(IOSRC) $(OSSRC) +VPATH = $(SRC) $(SRC)/mt $(IOSRC) $(OSSRC) include $(TOP)/config/CONFIG_BASE @@ -18,36 +18,37 @@ USR_INCLUDES = -I$(SRC) -I$(OSSRC) -I$(IOSRC) -I$(CA)\ DEPLIBS_BASE = $(EPICS_BASE_LIB) -SRCS.cc += $(SRC)/caServer.cc -SRCS.cc += $(SRC)/caServerI.cc -SRCS.cc += $(SRC)/casCoreClient.cc -SRCS.cc += $(SRC)/casClient.cc -SRCS.cc += $(SRC)/casDGClient.cc -SRCS.cc += $(SRC)/casStrmClient.cc -SRCS.cc += $(SRC)/casPV.cc -SRCS.cc += $(SRC)/casPVI.cc -SRCS.cc += $(SRC)/casChannel.cc -SRCS.cc += $(SRC)/casChannelI.cc -SRCS.cc += $(SRC)/casClientMon.cc -SRCS.cc += $(SRC)/casChanDelEv.cc -SRCS.cc += $(SRC)/casMsgIO.cc -SRCS.cc += $(SRC)/casAsyncIO.cc -SRCS.cc += $(SRC)/casAsyncIOI.cc -SRCS.cc += $(SRC)/casEventSys.cc -SRCS.cc += $(SRC)/casMonitor.cc -SRCS.cc += $(SRC)/casMonEvent.cc -SRCS.cc += $(SRC)/outBuf.cc -SRCS.cc += $(SRC)/inBuf.cc -SRCS.cc += $(SRC)/casEventMask.cc +SRCS.cc += caServer.cc +SRCS.cc += caServerI.cc +SRCS.cc += casCoreClient.cc +SRCS.cc += casClient.cc +SRCS.cc += casDGClient.cc +SRCS.cc += casStrmClient.cc +SRCS.cc += casPV.cc +SRCS.cc += casPVI.cc +SRCS.cc += casChannel.cc +SRCS.cc += casChannelI.cc +SRCS.cc += casClientMon.cc +SRCS.cc += casChanDelEv.cc +SRCS.cc += casMsgIO.cc +SRCS.cc += casAsyncIO.cc +SRCS.cc += casAsyncIOI.cc +SRCS.cc += casEventSys.cc +SRCS.cc += casMonitor.cc +SRCS.cc += casMonEvent.cc +SRCS.cc += outBuf.cc +SRCS.cc += inBuf.cc +SRCS.cc += casEventMask.cc +SRCS.cc += ioBlocked.cc -SRCS.cc += $(OSSRC)/caServerOS.cc -SRCS.cc += $(OSSRC)/casDGOS.cc -SRCS.cc += $(OSSRC)/casStreamOS.cc +SRCS.cc += caServerOS.cc +SRCS.cc += casDGOS.cc +SRCS.cc += casStreamOS.cc -SRCS.cc += $(IOSRC)/caServerIO.cc -SRCS.cc += $(IOSRC)/casDGIO.cc -SRCS.cc += $(IOSRC)/casStreamIO.cc -SRCS.c += $(IOSRC)/sigPipeIgnore.c +SRCS.cc += caServerIO.cc +SRCS.cc += casDGIO.cc +SRCS.cc += casStreamIO.cc +SRCS.c += sigPipeIgnore.c LIBOBJS += caServer.o LIBOBJS += caServerI.o @@ -70,6 +71,7 @@ LIBOBJS += casMonEvent.o LIBOBJS += outBuf.o LIBOBJS += inBuf.o LIBOBJS += casEventMask.o +LIBOBJS += ioBlocked.o LIBOBJS += caServerOS.o LIBOBJS += casDGOS.o diff --git a/src/cas/build/singleThread/Makefile.Unix b/src/cas/build/singleThread/Makefile.Unix index 4ca7224ae..10726ac93 100644 --- a/src/cas/build/singleThread/Makefile.Unix +++ b/src/cas/build/singleThread/Makefile.Unix @@ -6,48 +6,63 @@ TOP = $(CAS)/../.. SRC = $(CAS)/generic CA = $(CAS)/../ca IOSRC = $(CAS)/io/bsdSocket -OSSRC = $(CAS)/os/posix -VPATH = $(SRC) $(IOSRC) $(OSSRC) +STSRC = $(SRC)/st +VPATH = $(SRC) $(STSRC) $(IOSRC) include $(TOP)/config/CONFIG_BASE -CXXCMPLR = STRICT +# +# Too many errors from sun's include files +# +#CXXCMPLR = STRICT -USR_INCLUDES = -I$(SRC) -I$(OSSRC) -I$(IOSRC) -I$(CA) \ - -I$(TOP)/src/include/os/$(T_A) +USR_INCLUDES = -I$(SRC) -I$(IOSRC) -I$(STSRC) -I$(CA) DEPLIBS_BASE = $(EPICS_BASE_LIB) -SRCS.cc += $(SRC)/caServer.cc -SRCS.cc += $(SRC)/caServerI.cc -SRCS.cc += $(SRC)/casCoreClient.cc -SRCS.cc += $(SRC)/casClient.cc -SRCS.cc += $(SRC)/casDGClient.cc -SRCS.cc += $(SRC)/casStrmClient.cc -SRCS.cc += $(SRC)/casPV.cc -SRCS.cc += $(SRC)/casPVI.cc -SRCS.cc += $(SRC)/casChannel.cc -SRCS.cc += $(SRC)/casChannelI.cc -SRCS.cc += $(SRC)/casClientMon.cc -SRCS.cc += $(SRC)/casChanDelEv.cc -SRCS.cc += $(SRC)/casMsgIO.cc -SRCS.cc += $(SRC)/casAsyncIO.cc -SRCS.cc += $(SRC)/casAsyncIOI.cc -SRCS.cc += $(SRC)/casEventSys.cc -SRCS.cc += $(SRC)/casMonitor.cc -SRCS.cc += $(SRC)/casMonEvent.cc -SRCS.cc += $(SRC)/outBuf.cc -SRCS.cc += $(SRC)/inBuf.cc -SRCS.cc += $(SRC)/casEventMask.cc +SRCS.cc += caServer.cc +SRCS.cc += caServerI.cc +SRCS.cc += casCoreClient.cc +SRCS.cc += casClient.cc +SRCS.cc += casDGClient.cc +SRCS.cc += casStrmClient.cc +SRCS.cc += casPV.cc +SRCS.cc += casPVI.cc +SRCS.cc += casChannel.cc +SRCS.cc += casChannelI.cc +SRCS.cc += casClientMon.cc +SRCS.cc += casChanDelEv.cc +SRCS.cc += casMsgIO.cc +SRCS.cc += casAsyncIO.cc +SRCS.cc += casAsyncIOI.cc +SRCS.cc += casAsyncXXIO.cc +SRCS.cc += casAsyncRdIOI.cc +SRCS.cc += casAsyncWtIOI.cc +SRCS.cc += casAsyncExIOI.cc +SRCS.cc += casEventSys.cc +SRCS.cc += casMonitor.cc +SRCS.cc += casMonEvent.cc +SRCS.cc += inBuf.cc +SRCS.cc += outBuf.cc +SRCS.cc += dgInBuf.cc +SRCS.cc += dgOutBuf.cc +SRCS.cc += casCtx.cc +SRCS.cc += casEventMask.cc +SRCS.cc += ioBlocked.cc +SRCS.cc += templInst.cc -SRCS.cc += $(OSSRC)/caServerOS.cc -SRCS.cc += $(OSSRC)/casDGOS.cc -SRCS.cc += $(OSSRC)/casStreamOS.cc +SRCS.cc += caServerOS.cc +SRCS.cc += casIntfOS.cc +SRCS.cc += casDGIntfOS.cc +SRCS.cc += casDGOS.cc +SRCS.cc += casStreamOS.cc -SRCS.cc += $(IOSRC)/caServerIO.cc -SRCS.cc += $(IOSRC)/casDGIO.cc -SRCS.cc += $(IOSRC)/casStreamIO.cc -SRCS.c += $(IOSRC)/sigPipeIgnore.c +SRCS.cc += caServerIO.cc +SRCS.cc += casIntfIO.cc +SRCS.cc += casDGIntfIO.cc +SRCS.cc += casDGIO.cc +SRCS.cc += casStreamIO.cc +SRCS.c += sigPipeIgnore.c LIBOBJS += caServer.o LIBOBJS += caServerI.o @@ -64,20 +79,33 @@ LIBOBJS += casChanDelEv.o LIBOBJS += casMsgIO.o LIBOBJS += casAsyncIO.o LIBOBJS += casAsyncIOI.o +LIBOBJS += casAsyncXXIO.o +LIBOBJS += casAsyncRdIOI.o +LIBOBJS += casAsyncWtIOI.o +LIBOBJS += casAsyncExIOI.o LIBOBJS += casEventSys.o LIBOBJS += casMonitor.o LIBOBJS += casMonEvent.o -LIBOBJS += outBuf.o LIBOBJS += inBuf.o +LIBOBJS += outBuf.o +LIBOBJS += dgInBuf.o +LIBOBJS += dgOutBuf.o +LIBOBJS += casCtx.o LIBOBJS += casEventMask.o +LIBOBJS += ioBlocked.o +LIBOBJS += templInst.o LIBOBJS += caServerOS.o +LIBOBJS += casIntfOS.o +LIBOBJS += casDGIntfOS.o LIBOBJS += casDGOS.o LIBOBJS += casStreamOS.o LIBOBJS += caServerIO.o -LIBOBJS += casDGIO.o +LIBOBJS += casIntfIO.o +LIBOBJS += casDGIntfIO.o LIBOBJS += casStreamIO.o +LIBOBJS += casDGIO.o LIBOBJS += sigPipeIgnore.o LIBNAME = libcas.a diff --git a/src/cas/example/Makefile.Unix b/src/cas/example/Makefile.Unix index d8521e190..8d23de7f8 100644 --- a/src/cas/example/Makefile.Unix +++ b/src/cas/example/Makefile.Unix @@ -55,6 +55,7 @@ GLOMBOBJ += $(BUILDDIR)casMonEvent.o GLOMBOBJ += $(BUILDDIR)outBuf.o GLOMBOBJ += $(BUILDDIR)inBuf.o GLOMBOBJ += $(BUILDDIR)casEventMask.o +GLOMBOBJ += $(BUILDDIR)ioBlocked.o GLOMBOBJ += $(BUILDDIR)caServerOS.o GLOMBOBJ += $(BUILDDIR)casDGOS.o @@ -73,19 +74,19 @@ excas: $(OBJS) $(DEPLIBS) # # fast link (without waiting for library build) # -nolib: $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS) +fexcas: $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS) $(LINK.cc) -o $@ $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS) # # build with purify # -purify: $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS) - $(PURIFY) -best-effort $(LINK.cc) -o $@ $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS) +pexcas: $(OBJS) $(DEPLIBS) + $(PURIFY) $(LINK.cc) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS) clean:: @$(RM) excas - @$(RM) nolib - @$(RM) purify + @$(RM) fexcas + @$(RM) pexcas @$(RM) -rf Templates.DB @$(RM) core diff --git a/src/cas/example/exAsyncPV.cc b/src/cas/example/exAsyncPV.cc index 28a084fc9..63dcc9720 100644 --- a/src/cas/example/exAsyncPV.cc +++ b/src/cas/example/exAsyncPV.cc @@ -20,7 +20,7 @@ unsigned exAsyncPV::maxSimultAsyncOps () const // caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn) { - exAsyncIO *pIO; + exAsyncReadIO *pIO; pIO = new exAsyncReadIO(ctx, *this, valueIn); if (!pIO) { @@ -36,7 +36,7 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn) // caStatus exAsyncPV::write (const casCtx &ctx, gdd &valueIn) { - exAsyncIO *pIO; + exAsyncWriteIO *pIO; pIO = new exAsyncWriteIO(ctx, *this, valueIn); if (!pIO) { @@ -53,11 +53,18 @@ caStatus exAsyncPV::write (const casCtx &ctx, gdd &valueIn) void exAsyncWriteIO::expire() { caStatus status; - status = this->pv.update(*this->getValuePtr()); - this->clrValue(); + status = this->pv.update(this->value); this->postIOCompletion (status); } +// +// exAsyncWriteIO::name() +// +const char *exAsyncWriteIO::name() const +{ + return "exAsyncWriteIO"; +} + // // exAsyncReadIO::expire() // (a virtual function that runs when the base timer expires) @@ -65,17 +72,24 @@ void exAsyncWriteIO::expire() void exAsyncReadIO::expire() { caStatus status; - gdd *pValue = this->getValuePtr(); // // map between the prototype in and the // current value // - status = exServer::read(this->pv, *pValue); + status = exServer::read(this->pv, this->proto); // // post IO completion // - this->postIOCompletion(status); + this->postIOCompletion(status, this->proto); +} + +// +// exAsyncReadIO::name() +// +const char *exAsyncReadIO::name() const +{ + return "exAsyncReadIO"; } diff --git a/src/cas/example/exPV.cc b/src/cas/example/exPV.cc index b6e5e7e4d..cdea2b53f 100644 --- a/src/cas/example/exPV.cc +++ b/src/cas/example/exPV.cc @@ -103,7 +103,7 @@ void exScanTimer::expire () // // exScanTimer::again() // -osiBool exScanTimer::again() +osiBool exScanTimer::again() const { return osiTrue; } @@ -111,11 +111,19 @@ osiBool exScanTimer::again() // // exScanTimer::delay() // -const osiTime exScanTimer::delay() +const osiTime exScanTimer::delay() const { return pv.getScanRate(); } +// +// exScanTimer::name() +// +const char *exScanTimer::name() const +{ + return "exScanTimer"; +} + // // exPV::update () // @@ -135,11 +143,12 @@ caStatus exPV::update(gdd &valueIn) return S_casApp_noSupport; } -# if DEBUG - printf("%s = %f\n", - this->info.getName().string, valueIn); +# if DEBUG + printf("Setting %s too:\n", this->info.getName().string()); + valueIn.dump(); # endif + if (valueIn.isScalar()) { pNewValue = &valueIn; pNewValue->reference(); diff --git a/src/cas/example/exServer.cc b/src/cas/example/exServer.cc index 492f6299d..891b1d078 100644 --- a/src/cas/example/exServer.cc +++ b/src/cas/example/exServer.cc @@ -49,8 +49,7 @@ exServer::exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate, // // exServer::pvExistTest() // -caStatus exServer::pvExistTest(const casCtx &ctxIn, const char *pPVName, - gdd &canonicalPVName) +pvExistReturn exServer::pvExistTest(const casCtx &ctxIn, const char *pPVName) { const pvInfo *pPVI; @@ -58,24 +57,20 @@ caStatus exServer::pvExistTest(const casCtx &ctxIn, const char *pPVName, if (pPVI) { if (pPVI->getIOType()==excasIoAsync) { exAsyncExistIO *pIO; - pIO = new exAsyncExistIO(pPVI, ctxIn, canonicalPVName); + pIO = new exAsyncExistIO(*pPVI, ctxIn); if (pIO) { - return S_casApp_asyncCompletion; + return pvExistReturn(S_casApp_asyncCompletion); } else { - return S_casApp_noMemory; + return pvExistReturn(S_casApp_noMemory); } } - // - // there are no name aliases in this - // server's PV name syntax - // - canonicalPVName.put (pPVI->getName()); - return S_casApp_success; + const char *pName = pPVI->getName(); + return pvExistReturn(S_casApp_success, pName); } - return S_casApp_pvNotFound; + return pvExistReturn(S_casApp_pvNotFound); } // @@ -138,7 +133,7 @@ void exServer::show (unsigned level) // destroy so the exAsyncIO class will hang around until the // casAsyncIO::destroy() is called // -void exAsyncIOTimer::destroy() +void exOSITimer::destroy() { } @@ -148,9 +143,19 @@ void exAsyncIOTimer::destroy() // void exAsyncExistIO::expire() { + const char *pName = pvi.getName(); + // // post IO completion // - this->postIOCompletion(S_cas_success); + this->postIOCompletion (pvExistReturn(S_cas_success, pName)); +} + +// +// exAsyncExistIO::name() +// +const char *exAsyncExistIO::name() const +{ + return "exAsyncExistIO"; } diff --git a/src/cas/example/exServer.h b/src/cas/example/exServer.h index eafb30fc2..08f1f29f5 100644 --- a/src/cas/example/exServer.h +++ b/src/cas/example/exServer.h @@ -97,12 +97,9 @@ public: exScanTimer (double delayIn, exPV &pvIn) : pv(pvIn), osiTimer(delayIn) {} void expire (); - osiBool again(); - const osiTime delay(); - const char *name() - { - return "exScanTimer"; - } + osiBool again() const; + const osiTime delay() const; + const char *name() const; private: exPV &pv; }; @@ -188,8 +185,7 @@ public: exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate=0x3ff, unsigned maxSimultaneousIO=1u); void show (unsigned level); - caStatus pvExistTest (const casCtx &ctxIn, const char *pPVName, - gdd &canonicalPVName); + pvExistReturn pvExistTest (const casCtx &ctxIn, const char *pPVName); casPV *createPV (const casCtx &ctxIn, const char *pPVName); static const pvInfo *findPV(const char *pName); @@ -281,46 +277,44 @@ public: private: }; - // -// exAsyncIOTimer +// exOSITimer // -class exAsyncIOTimer : public osiTimer { +// a special version of osiTimer which is only to be used +// within an exAsyncIO. The destroy() method is replaced +// so that the timer destroy() will not destroy the +// exAsyncIO until the casAsyncIO has completed +// +class exOSITimer : public osiTimer { public: - exAsyncIOTimer (osiTime delayIn) : osiTimer(delayIn) {} + exOSITimer() : osiTimer(osiTime(0.010)) {} // 10 mSec + // // this is a noop that postpones the timer expiration // destroy so this object will hang around until the // casAsyncIO::destroy() is called // void destroy(); - - const char *name() - { - return "exAsyncIOTimer"; - } -}; - -// -// exAsyncIO() -// -class exAsyncIO : public casAsyncIO, public exAsyncIOTimer { -public: - exAsyncIO(const casCtx &ctxIn, gdd *pValue = 0) : - casAsyncIO(ctxIn, pValue), - exAsyncIOTimer(osiTime(0.010)) {} // 10 mSec }; // // exAsyncWriteIO // -class exAsyncWriteIO : public exAsyncIO { +class exAsyncWriteIO : public casAsyncWriteIO, public exOSITimer { public: // // exAsyncWriteIO() // exAsyncWriteIO(const casCtx &ctxIn, exAsyncPV &pvIn, gdd &valueIn) : - exAsyncIO(ctxIn, &valueIn), pv(pvIn) {} + casAsyncWriteIO(ctxIn), pv(pvIn), value(valueIn) + { + this->value.reference(); + } + + ~exAsyncWriteIO() + { + this->value.unreference(); + } // // expire() @@ -328,20 +322,32 @@ public: // see exAsyncPV.cc // void expire(); + + const char *name() const; + private: exAsyncPV &pv; + gdd &value; }; // // exAsyncReadIO // -class exAsyncReadIO : public exAsyncIO { +class exAsyncReadIO : public casAsyncReadIO, public exOSITimer { public: // // exAsyncReadIO() // exAsyncReadIO(const casCtx &ctxIn, exAsyncPV &pvIn, gdd &protoIn) : - exAsyncIO(ctxIn, &protoIn), pv(pvIn) {} + casAsyncReadIO(ctxIn), pv(pvIn), proto(protoIn) + { + this->proto.reference(); + } + + ~exAsyncReadIO() + { + this->proto.unreference(); + } // // expire() @@ -350,25 +356,24 @@ public: // void expire(); + const char *name() const; + private: exAsyncPV &pv; + gdd &proto; }; // // exAsyncExistIO // (PV exist async IO) // -class exAsyncExistIO : public exAsyncIO { +class exAsyncExistIO : public casAsyncPVExistIO, public exOSITimer { public: // // exAsyncExistIO() // - exAsyncExistIO(const pvInfo *pPVI, - const casCtx &ctxIn, gdd &canonicalPVName) : - exAsyncIO(ctxIn, &canonicalPVName) - { - canonicalPVName.put (pPVI->getName()); - } + exAsyncExistIO(const pvInfo &pviIn, const casCtx &ctxIn) : + casAsyncPVExistIO(ctxIn), pvi(pviIn) {} // // expire() @@ -376,7 +381,10 @@ public: // see exServer.cc // void expire(); + + const char *name() const; private: + const pvInfo &pvi; }; diff --git a/src/cas/example/main.cc b/src/cas/example/main.cc index 8105ad523..a973b036f 100644 --- a/src/cas/example/main.cc +++ b/src/cas/example/main.cc @@ -4,6 +4,7 @@ // // main() +// (example single threaded ca server tool main loop) // int main (int argc, const char **argv) { diff --git a/src/cas/generic/README b/src/cas/generic/README index 012dcde28..ebbf53e75 100644 --- a/src/cas/generic/README +++ b/src/cas/generic/README @@ -1,6 +1,43 @@ -this directory contains the generic (os and io independent) source for +This directory contains the generic (os and io independent) source for the EPICS ca server library +The sub-diretory "mt" contains multi-threaded specific code and the +sub-directory "st" contains single-threaded specific code. + +Design Notes: +1) When I was preparing a thread-safe version of the server lib I assumed +that all locking required to protect gdd::reference() and gdd::unreference() +will be provided by the gdd library. + +2) The source file "templInst.cc" attempts to provide explicit instantiation +of the template member functions required following the ANSI resolution +r.14.9 in appendix A of Stroustrup's book. The problem is that Sun's +compiler does not recognize this syntax so we must "ifdef" the code until +this matter is resolved. + +Here are some of the inheritance trees used by the server lib: + + casCoreClient + | + | +inBuf outBuf casClient dgInBuf dgOutBuf +| | |_______________________ | | +| | | | | | +|_______casStrmClient casDGClient_____| + | | + | | + casStreamIO casDGIO + | | + | | + casStreamOS casDGOS + + + casDGIntfIO casIntfIO + | | + | | + casDGIntfOS casIntfOS + + diff --git a/src/cas/generic/caCommonDef.h b/src/cas/generic/caCommonDef.h index 5890c03f2..370a0e864 100644 --- a/src/cas/generic/caCommonDef.h +++ b/src/cas/generic/caCommonDef.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/08/05 19:24:23 jhill + * removed ERROR and OK + * * Revision 1.1.1.1 1996/06/20 00:28:15 jhill * ca server installation * @@ -36,8 +39,8 @@ */ -#ifndef includeCasCommonDefH -#define includeCasCommonDefH +#ifndef includeCaCommonDefH +#define includeCaCommonDefH #ifndef NULL #define NULL 0 @@ -67,5 +70,5 @@ #define max(A,B) ((A)<(B)?(B):(A)) #endif -#endif /* ifndef includeCasCommonDefH (last line in this file) */ +#endif /* ifndef includeCaCommonDefH (last line in this file) */ diff --git a/src/cas/generic/caServer.cc b/src/cas/generic/caServer.cc index e247326e8..2c4494bdf 100644 --- a/src/cas/generic/caServer.cc +++ b/src/cas/generic/caServer.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.3 1996/09/16 18:23:56 jhill + * vxWorks port changes + * * Revision 1.2 1996/06/21 02:30:52 jhill * solaris port * @@ -39,6 +42,7 @@ */ #include +#include // caServerI in line func #include // ait to dbr types #include // EPICS application type table @@ -61,7 +65,6 @@ caServer::caServer(unsigned pvMaxNameLengthIn, unsigned pvCountEstimateIn, logEventMask(this->registerEvent("log")), alarmEventMask(this->registerEvent("alarm")) { - caStatus status; static init; if (!init) { @@ -69,21 +72,16 @@ caServer::caServer(unsigned pvMaxNameLengthIn, unsigned pvCountEstimateIn, init = TRUE; } - // - // OS and IO dependent - // if (!this->pCAS) { errMessage(S_cas_noMemory, NULL); return; } - status = this->pCAS->init(); - if (status) { - errMessage(status, NULL); + if (!this->pCAS->ready()) { delete this->pCAS; this->pCAS = NULL; - return; - } + return; + } } // @@ -106,6 +104,7 @@ casEventMask caServer::registerEvent (const char *pName) } else { casEventMask emptyMask; + printf("caServer:: no server internals attached\n"); return emptyMask; } } @@ -132,7 +131,7 @@ void caServer::setDebugLevel (unsigned level) this->pCAS->setDebugLevel(level); } else { - errMessage(S_cas_noMemory, NULL); + printf("caServer:: no server internals attached\n"); } } @@ -145,8 +144,24 @@ unsigned caServer::getDebugLevel () return this->pCAS->getDebugLevel(); } else { - errMessage(S_cas_noMemory, NULL); + printf("caServer:: no server internals attached\n"); return 0u; } } - + +// +// This must be virtual so that derived destructor will +// be run indirectly. Therefore it cannot be inline. +// +casRes::~casRes() +{ +} + +// +// This must be virtual so that derived destructor will +// be run indirectly. Therefore it cannot be inline. +// +casEvent::~casEvent() +{ +} + diff --git a/src/cas/generic/caServerI.cc b/src/cas/generic/caServerI.cc index 3dfdf4d3e..51cb5b9bb 100644 --- a/src/cas/generic/caServerI.cc +++ b/src/cas/generic/caServerI.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.5 1996/09/16 18:23:56 jhill + * vxWorks port changes + * * Revision 1.4 1996/09/04 20:12:04 jhill * added arg to serverToolDebugFunc() * @@ -48,8 +51,10 @@ #define caServerGlobal #include +#include // casCtx in line func -VERSIONID(casAccessc,"%W% %G%") +static const osiTime CAServerMaxBeaconPeriod (5.0 /* sec */); +static const osiTime CAServerMinBeaconPeriod (1.0e-3 /* sec */); // @@ -58,7 +63,6 @@ VERSIONID(casAccessc,"%W% %G%") void caServerI::show (unsigned level) { casStrmClient *pClient; - tsDLIter iter(this->clientList); int bytes_reserved; printf( "Channel Access Server Status V%d.%d\n", @@ -67,11 +71,18 @@ void caServerI::show (unsigned level) this->osiMutex::show(level); this->osiLock(); - while ( (pClient = iter()) ) { + tsDLFwdIter iterCl(this->clientList); + while ( (pClient = iterCl.next()) ) { pClient->show(level); } - this->dgClient.show(level); + + casIntfOS *pIF; + tsDLFwdIter iterIF(this->intfList); + while ( (pIF = iterIF.next()) ) { + pIF->show(level); + } + this->osiUnlock(); bytes_reserved = 0u; @@ -120,6 +131,8 @@ void caServerI::show (unsigned level) // caServerI::caServerI (caServer &tool, unsigned maxNameLength, unsigned nPV, unsigned maxSimultIO) : + caServerOS(*this), + casEventRegistry(* (osiMutex *) this), dgClient(*this), // // Set up periodic beacon interval @@ -134,10 +147,17 @@ caServerI::caServerI (caServer &tool, unsigned maxNameLength, pvMaxNameLength(maxNameLength), pvCountEstimate(nPV<100u?100u:nPV), maxSimultaneousIO(maxSimultIO), - caServerOS(*this) + haveBeenInitialized(FALSE) { + caStatus status; + assert(&adapter); ctx.setServer(this); + + status = this->init(); + if (status) { + errMessage(status, "CA server internals init"); + } } @@ -146,18 +166,27 @@ caServerI::caServerI (caServer &tool, unsigned maxNameLength, // caStatus caServerI::init() { - int status; - int resLibStatus; + int status; + int resLibStatus; if (this->osiMutex::init()) { return S_cas_noMemory; } - status = caServerIO::init(); + status = casEventRegistry::init(); if (status) { return status; } + status = caServerIO::init(*this); + if (status) { + return status; + } + + if (this->intfList.count()==0u) { + return S_cas_noInterface; + } + status = caServerOS::init(); if (status) { return status; @@ -186,6 +215,7 @@ caStatus caServerI::init() return S_cas_noMemory; } + this->haveBeenInitialized = TRUE; return S_cas_success; } @@ -196,15 +226,24 @@ caStatus caServerI::init() */ caServerI::~caServerI() { - casClient *pClient; this->osiLock(); // // delete all clients // - while ( (pClient = this->clientList.get()) ) { + casClient *pClient; + tsDLFwdIter iter(this->clientList); + pClient = iter.next(); + while (pClient) { + casClient *pNextClient = iter.next(); delete pClient; + pClient = pNextClient; + } + + casIntfOS *pIF; + while ( (pIF = this->intfList.get()) ) { + delete pIF; } this->osiUnlock(); @@ -241,31 +280,17 @@ void caServerI::removeClient(casStrmClient *pClient) // // caServerI::connectCB() // -void caServerI::connectCB() +void caServerI::connectCB(casIntfOS &intf) { casStreamOS *pNewClient; - casMsgIO *pIO; caStatus status; - pIO = this->newStreamIO(); - if (!pIO) { + pNewClient = intf.newStreamClient(*this); + if (!pNewClient) { errMessage(S_cas_noMemory, NULL); return; } - status = pIO->init(); - if (status) { - errMessage(status, NULL); - delete pIO; - return; - } - - pNewClient = new casStreamOS(*this, *pIO); - if (!pNewClient) { - errMessage(S_cas_noMemory, NULL); - return; - } - status = pNewClient->init(); if (status) { errMessage(status, NULL); @@ -300,9 +325,11 @@ void caServerI::advanceBeaconPeriod() // void casVerifyFunc(const char *pFile, unsigned line, const char *pExp) { + fprintf(stderr, "the expression \"%s\" didnt evaluate to boolean true \n", + pExp); fprintf(stderr, -"We suspect internal problems at line %u in \"%s\" because \"%s\"==0\n", - line, pFile, pExp); +"and therefore internal problems are suspected at line %u in \"%s\"\n", + line, pFile); fprintf(stderr, "Please forward above text to johill@lanl.gov - thanks\n"); } @@ -317,3 +344,60 @@ void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment) line, pFile, pComment); } +// +// caServerI::addAddr() +// +caStatus caServerI::addAddr(const caAddr &caAddr, int autoBeaconAddr, + int addConfigBeaconAddr) +{ + caStatus stat; + casIntfOS *pIntf; + + pIntf = new casIntfOS(*this); + if (pIntf) { + stat = pIntf->init(caAddr, this->dgClient, + autoBeaconAddr, addConfigBeaconAddr); + if (stat==S_cas_success) { + this->osiLock(); + this->intfList.add(*pIntf); + this->osiUnlock(); + } + else { + errMessage(stat, NULL); + delete pIntf; + } + } + else { + stat = S_cas_noMemory; + } + return stat; +} + + +// +// caServerI::sendBeacon() +// (implemented here because this has knowledge of the protocol) +// +void caServerI::sendBeacon() +{ + casIntfOS *pIntf; + + // + // send a broadcast beacon over each configured + // interface unless EPICS_CA_AUTO_ADDR_LIST specifies + // otherwise. Also send a beacon to all configured + // addresses. + // + this->osiLock(); + tsDLFwdIter iter(this->intfList); + while ( (pIntf = iter.next()) ) { + pIntf->requestBeacon(); + } + this->osiUnlock(); + + // + // double the period between beacons (but dont exceed max) + // + this->advanceBeaconPeriod(); +} + diff --git a/src/cas/generic/caServerIIL.h b/src/cas/generic/caServerIIL.h index 3d1d385e9..8ef1d1b4e 100644 --- a/src/cas/generic/caServerIIL.h +++ b/src/cas/generic/caServerIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/09/16 18:23:57 jhill + * vxWorks port changes + * * Revision 1.1.1.1 1996/06/20 00:28:16 jhill * ca server installation * @@ -39,6 +42,22 @@ #ifndef caServerIIL_h #define caServerIIL_h +// +// caServerI::getAdapter() +// +inline caServer *caServerI::getAdapter() +{ + return &this->adapter; +} + +// +// call virtual function in the interface class +// +inline caServer * caServerI::operator -> () +{ + return this->getAdapter(); +} + // // caServerI::lookupRes() // @@ -47,12 +66,14 @@ inline casRes *caServerI::lookupRes(const caResId &idIn, casResType type) uintId id(idIn); casRes *pRes; + this->osiLock(); pRes = this->uintResTable::lookup(id); if (pRes) { if (pRes->resourceType()!=type) { - pRes = 0; + pRes = NULL; } } + this->osiUnlock(); return pRes; } @@ -86,14 +107,19 @@ inline aitBool caServerI::pvExistTestPossible() // // find the channel associated with a resource id // -inline caStatus caServerI::pvExistTest(const casCtx &ctxIn, - const char *pPVName, gdd &canonicalPVName) +inline pvExistReturn caServerI::pvExistTest( + const casCtx &ctxIn, const char *pPVName) { - if (!pvExistTestPossible()) { - return S_cas_ioBlocked; + this->osiLock(); + if (pvExistTestPossible()) { + this->nExistTestInProg++; + osiUnlock(); + return (*this)->pvExistTest(ctxIn, pPVName); + } + else { + osiUnlock(); + return pvExistReturn(S_cas_ioBlocked); } - this->nExistTestInProg++; - return (*this)->pvExistTest(ctxIn, pPVName, canonicalPVName); } // @@ -101,7 +127,9 @@ inline caStatus caServerI::pvExistTest(const casCtx &ctxIn, // inline void caServerI::pvExistTestCompletion() { + this->osiLock(); this->nExistTestInProg--; + this->osiUnlock(); this->ioBlockedList::signal(); } @@ -136,5 +164,50 @@ inline void caServerI::removePV(casPVI &pv) casVerify (pPV==&pv); } +// +// caServerI::getPVMaxNameLength() +// +inline unsigned caServerI::getPVMaxNameLength() const +{ + return this->pvMaxNameLength; +} + +// +// caServerI::installItem() +// +inline void caServerI::installItem(casRes &res) +{ + this->uintResTable::installItem(res); +} + +// +// caServerI::removeItem() +// +inline casRes *caServerI::removeItem(casRes &res) +{ + return this->uintResTable::remove(res); +} + +// +// caServerI::ready() +// +inline aitBool caServerI::ready() +{ + if (this->haveBeenInitialized) { + return aitTrue; + } + else { + return aitFalse; + } +} + +// +// caServerI::setDebugLevel() +// +inline void caServerI::setDebugLevel(unsigned debugLevelIn) +{ + this->debugLevel = debugLevelIn; +} + #endif // caServerIIL_h diff --git a/src/cas/generic/casAsyncIO.cc b/src/cas/generic/casAsyncIO.cc index 616f1117a..fcabdc884 100644 --- a/src/cas/generic/casAsyncIO.cc +++ b/src/cas/generic/casAsyncIO.cc @@ -29,14 +29,25 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:14 jhill + * ca server installation + * * */ - #include +// +// This must be virtual so that derived destructor will +// be run indirectly. Therefore it cannot be inline. +// +casAsyncIO::~casAsyncIO() +{ +} + // // casAsyncIO::destroy() +// (default is a normal delete) // void casAsyncIO::destroy() { diff --git a/src/cas/generic/casAsyncIOI.cc b/src/cas/generic/casAsyncIOI.cc index ba6d9b6c5..a017ee7fa 100644 --- a/src/cas/generic/casAsyncIOI.cc +++ b/src/cas/generic/casAsyncIOI.cc @@ -29,53 +29,26 @@ * * History * $Log$ - * Revision 1.2 1996/06/26 21:18:50 jhill - * now matches gdd api revisions - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * * */ #include -#include // casAsyncIOI inline func -#include // casChannelI inline func -#include // casEventSys inline func +#include // casEventSys in line func +#include // casAsyncIOI in line func +#include // casCtx in line func // // casAsyncIOI::casAsyncIOI() // -casAsyncIOI::casAsyncIOI(const casCtx &ctx, casAsyncIO &ioIn, gdd *pDD) : - msg(*ctx.getMsg()), - client(*ctx.getClient()), - asyncIO(ioIn), - pChan(ctx.getChannel()), - pDesc(pDD), - completionStatus(S_cas_internal), +casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn) : + client(clientIn), + ioExternal(ioExternalIn), inTheEventQueue(FALSE), posted(FALSE), ioComplete(FALSE), serverDelete(FALSE) { - assert (&this->client); - assert (&this->msg); - assert (&this->asyncIO); - - if (this->pChan) { - this->pChan->installAsyncIO(*this); - } - else { - this->client.installAsyncIO(*this); - } - - if (this->pDesc) { - int gddStatus; - - gddStatus = this->pDesc->reference(); - assert(!gddStatus); - } } // @@ -108,7 +81,6 @@ casAsyncIOI::casAsyncIOI(const casCtx &ctx, casAsyncIO &ioIn, gdd *pDD) : // casAsyncIOI::~casAsyncIOI() { - this->lock(); if (!this->serverDelete) { @@ -117,20 +89,13 @@ casAsyncIOI::~casAsyncIOI() fprintf(stderr, "WARNING: by the server tool. This results in no IO cancel\n"); fprintf(stderr, - "WARNING: message being sent to the client. PLease cancel\n"); + "WARNING: message being sent to the client. Please cancel\n"); fprintf(stderr, "WARNING: IO by posting S_casApp_canceledAsyncIO instead of\n"); fprintf(stderr, "WARNING: by deleting the async IO object.\n"); } - if (this->pChan) { - this->pChan->removeAsyncIO(*this); - } - else { - this->client.removeAsyncIO(*this); - } - // // pulls itself out of the event queue // if it is installed there @@ -139,14 +104,6 @@ casAsyncIOI::~casAsyncIOI() this->client.casEventSys::removeFromEventQueue(*this); } - if (this->pDesc) { - int gddStatus; - - gddStatus = this->pDesc->unreference(); - assert (gddStatus==0); - this->pDesc = NULL; - } - this->unlock(); } @@ -157,14 +114,19 @@ casAsyncIOI::~casAsyncIOI() // caStatus casAsyncIOI::cbFunc(class casEventSys &) { - caStatus status; + casCoreClient &theClient = this->client; + caStatus status; - this->lock(); + // + // Use the client's lock here (which is the same as the + // asynch IO's lock) here because we need to leave the lock + // applied arround the destroy() call here. + // + theClient.osiLock(); this->inTheEventQueue = FALSE; - status = this->client.asyncIOCompletion(this->pChan, - this->msg, this->pDesc, this->completionStatus); + status = this->cbFuncAsyncIO(); if (status == S_cas_sendBlocked) { // @@ -178,24 +140,25 @@ caStatus casAsyncIOI::cbFunc(class casEventSys &) errMessage (status, "Asynch IO completion failed"); } - // - // dont use "this" after this delete - // this->ioComplete = TRUE; - this->unlock(); - - this->setServerDelete(); + // + // dont use "this" after potentially destroying the + // object here + // + this->serverDelete = TRUE; (*this)->destroy(); + theClient.osiUnlock(); + return S_cas_success; } // -// casAsyncIOI::postIOCompletion() +// casAsyncIOI::postIOCompletionI() // -caStatus casAsyncIOI::postIOCompletion(caStatus completionStatusIn, gdd *pValue) +caStatus casAsyncIOI::postIOCompletionI() { this->lock(); @@ -211,28 +174,6 @@ caStatus casAsyncIOI::postIOCompletion(caStatus completionStatusIn, gdd *pValue) // dont call the server tool's cancel() when this object deletes // this->posted = TRUE; - this->completionStatus = completionStatusIn; - - if (pValue) { - int gddStatus; - - gddStatus = pValue->reference(); - assert(!gddStatus); - - if (this->pDesc) { - gddStatus = this->pDesc->unreference(); - assert (gddStatus==0); - } - - this->pDesc = pValue; - } - - // - // No changes after the IO completes - // - if (this->pDesc) { - pDesc->markConstant(); - } // // place this event in the event queue @@ -255,3 +196,43 @@ caServer *casAsyncIOI::getCAS() return this->client.getCAS().getAdapter(); } +// +// casAsyncIOI::readOP() +// +int casAsyncIOI::readOP() +{ + // + // not a read op + // + return FALSE; +} + +// +// casAsyncIOI::destroyIfReadOP() +// +void casAsyncIOI::destroyIfReadOP() +{ + // + // client lock used because this object's + // lock may be destroyed + // + this->client.osiLock(); + + if (this->readOP()) { + this->serverDelete = TRUE; + (*this)->destroy(); + } + + this->client.osiUnlock(); +} + +// +// casAsyncIOI::reportInvalidAsynchIO() +// +void casAsyncIOI::reportInvalidAsynchIO(unsigned request) +{ + ca_printf("Server tools selection of async IO type\n"); + ca_printf("is inappropriate = %u and will be ignored\n", + request); +} + diff --git a/src/cas/generic/casAsyncIOIIL.h b/src/cas/generic/casAsyncIOIIL.h index 73b2fecf6..25e73f00e 100644 --- a/src/cas/generic/casAsyncIOIIL.h +++ b/src/cas/generic/casAsyncIOIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.3 1996/09/16 18:23:58 jhill + * vxWorks port changes + * * Revision 1.2 1996/09/04 20:16:24 jhill * moved operator -> here * @@ -45,6 +48,11 @@ // // void casAsyncIOI::lock() // +// NOTE: +// If this changed to use another lock other than the one in the +// client structure then the locking in casAsyncIOI::cbFunc() +// must be changed +// inline void casAsyncIOI::lock() { client.osiLock(); @@ -63,7 +71,16 @@ inline void casAsyncIOI::unlock() // inline casAsyncIO * casAsyncIOI::operator -> () { - return &this->asyncIO; + return &this->ioExternal; +} + +// +// void casAsyncIOI::destroy () +// +inline void casAsyncIOI::destroy () +{ + this->serverDelete = TRUE; + (*this)->destroy(); } #endif // casAsyncIOIIL_h diff --git a/src/cas/generic/casChanDelEv.cc b/src/cas/generic/casChanDelEv.cc index a129c1c9c..75ae7f47e 100644 --- a/src/cas/generic/casChanDelEv.cc +++ b/src/cas/generic/casChanDelEv.cc @@ -29,11 +29,15 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:15 jhill + * ca server installation + * * */ #include +#include // casEventSys in line func // // casChanDelEv() diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index ebf9051fe..3b9f5767b 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/09/04 20:18:03 jhill + * init new chan member + * * Revision 1.1.1.1 1996/06/20 00:28:14 jhill * ca server installation * @@ -39,6 +42,7 @@ #include // casEventSys inline func #include // casAsyncIOI inline func #include // casPVI inline func +#include // casCtx inline func // @@ -64,9 +68,7 @@ casChannelI::casChannelI(const casCtx &ctx, casChannel &chanAdapter) : casChannelI::~casChannelI() { casAsyncIOI *pIO; - tsDLIter iterIO(this->ioInProgList); casMonitor *pMonitor; - tsDLIter iterMon(this->monitorList); casChanDelEv *pCDEV; caStatus status; @@ -75,28 +77,29 @@ casChannelI::~casChannelI() // // cancel any pending asynchronous IO // - pIO = iterIO(); + tsDLFwdIter iterIO(this->ioInProgList); + pIO = iterIO.next(); while (pIO) { casAsyncIOI *pNextIO; // // destructor removes from this list // - pNextIO = iterIO(); - pIO->setServerDelete(); - (*pIO)->destroy(); + pNextIO = iterIO.next(); + pIO->destroy(); pIO = pNextIO; } // // cancel the monitors // - pMonitor = iterMon(); + tsDLFwdIter iterMon(this->monitorList); + pMonitor = iterMon.next(); while (pMonitor) { casMonitor *pNextMon; // // destructor removes from this list // - pNextMon = iterMon(); + pNextMon = iterMon.next(); delete pMonitor; pMonitor = pNextMon; } @@ -132,6 +135,34 @@ casChannelI::~casChannelI() this->unlock(); } + +// +// casChannelI::clearOutstandingReads() +// +void casChannelI::clearOutstandingReads() +{ + casAsyncIOI *pIO; + + this->lock(); + + // + // cancel any pending asynchronous IO + // + tsDLFwdIter iterIO(this->ioInProgList); + pIO = iterIO.next(); + while (pIO) { + casAsyncIOI *pNextIO; + // + // destructor removes from this list + // + pNextIO = iterIO.next(); + pIO->destroyIfReadOP(); + pIO = pNextIO; + } + + this->unlock(); +} + // // casChannelI::postAllModifiedEvents() @@ -139,10 +170,10 @@ casChannelI::~casChannelI() void casChannelI::postAllModifiedEvents() { casMonitor *pMon; - tsDLIter iter(this->monitorList); this->lock(); - while ( (pMon=iter()) ) { + tsDLFwdIter iter(this->monitorList); + while ( (pMon=iter.next()) ) { pMon->postIfModified(); } this->unlock(); @@ -155,18 +186,18 @@ void casChannelI::postAllModifiedEvents() void casChannelI::show(unsigned level) { casMonitor *pMon; - tsDLIter iter(this->monitorList); this->lock(); + tsDLFwdIter iter(this->monitorList); - if ( (pMon = iter()) ) { + if ( (pMon = iter.next()) ) { printf("List of CA events (monitors) for \"%s\".\n", this->pv.resourceName()); } while (pMon) { pMon->show(level); - pMon = iter(); + pMon = iter.next(); } (*this)->show(level); diff --git a/src/cas/generic/casChannelIIL.h b/src/cas/generic/casChannelIIL.h index 78585290d..c860bd015 100644 --- a/src/cas/generic/casChannelIIL.h +++ b/src/cas/generic/casChannelIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.4 1996/09/16 18:23:59 jhill + * vxWorks port changes + * * Revision 1.3 1996/09/04 20:18:27 jhill * moved operator -> here * @@ -45,6 +48,8 @@ #ifndef casChannelIIL_h #define casChannelIIL_h +#include + // // casChannelI::operator -> () // @@ -75,10 +80,10 @@ inline void casChannelI::unlock() inline void casChannelI::postEvent(const casEventMask &select, gdd &event) { casMonitor *pMon; - tsDLIter iter(this->monitorList); this->lock(); - while ( (pMon = iter()) ) { + tsDLFwdIter iter(this->monitorList); + while ( (pMon = iter.next()) ) { pMon->post(select, event); } this->unlock(); @@ -95,8 +100,8 @@ inline void casChannelI::deleteMonitor(casMonitor &mon) this->getClient().casEventSys::removeMonitor(); this->monitorList.remove(mon); pRes = this->getClient().getCAS().removeItem(mon); - assert(&mon == (casMonitor *)pRes); this->unlock(); + assert(&mon == (casMonitor *)pRes); } // @@ -119,14 +124,16 @@ inline void casChannelI::addMonitor(casMonitor &mon) // inline casMonitor *casChannelI::findMonitor(const caResId clientIdIn) { - tsDLIter iter(this->monitorList); casMonitor *pMon; - while ( (pMon = iter()) ) { + this->lock(); + tsDLFwdIter iter(this->monitorList); + while ( (pMon = iter.next()) ) { if ( clientIdIn == pMon->getClientId()) { return pMon; } } + this->unlock(); return NULL; } diff --git a/src/cas/generic/casClient.cc b/src/cas/generic/casClient.cc index b3f8ec0e1..cc8a248ad 100644 --- a/src/cas/generic/casClient.cc +++ b/src/cas/generic/casClient.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.4 1996/09/04 20:19:02 jhill + * include db_access.h + * * Revision 1.3 1996/08/13 22:56:13 jhill * added init for mutex class * @@ -44,6 +47,9 @@ #include #include // inline func for casClient +#include // inline func for casEventSys +#include // inline func for casCtx +#include // inline func for inBuf #include VERSIONID(camsgtaskc,"%W% %G%") @@ -62,11 +68,9 @@ pCASMsgHandler casClient::msgHandlers[CA_PROTO_LAST_CMMD+1u]; // // casClient::casClient() // -casClient::casClient(caServerI &serverInternal, casMsgIO &msgIOIn) : - inBuf(msgIOIn, *this), - outBuf(msgIOIn, *this), - casCoreClient(serverInternal), - msgIO(msgIOIn) +casClient::casClient(caServerI &serverInternal, inBuf &inBufIn, outBuf &outBufIn) : + casCoreClient(serverInternal), + inBufRef(inBufIn), outBufRef(outBufIn) { // // static member init @@ -86,14 +90,6 @@ caStatus casClient::init() // // call base class initializers // - status = this->inBuf::init(); - if (status) { - return status; - } - status = this->outBuf::init(); - if (status) { - return status; - } status = this->casCoreClient::init(); if (status) { return status; @@ -101,8 +97,10 @@ caStatus casClient::init() serverDebugLevel = this->ctx.getServer()->getDebugLevel(); if (serverDebugLevel>0u) { - ca_printf("CAS: created a new client for\n"); - this->msgIO.show(serverDebugLevel); + char pName[64u]; + + this->clientHostName (pName, sizeof (pName)); + ca_printf("CAS: created a new client for %s\n", pName); } return S_cas_success; @@ -192,13 +190,10 @@ casClient::~casClient () // // casClient::show() // -void casClient::show(unsigned level) +void casClient::show(unsigned level) const { printf ("casClient at %x\n", (unsigned) this); this->casCoreClient::show(level); - this->inBuf::show(level); - this->outBuf::show(level); - this->msgIO.show(level); } @@ -213,17 +208,20 @@ caStatus casClient::processMsg() const caHdr *mp; const char *rawMP; - /* - * parse all any pending messages - */ - bytesLeft = this->inBuf::bytesPresent(); + // + // process any messages in the in buffer + // + status = S_cas_success; + + bytesLeft = this->inBufRef.bytesPresent(); while (bytesLeft) { if (bytesLeft < sizeof(*mp)) { - return S_cas_partialMessage; + status = S_cas_partialMessage; + break; } - rawMP = this->inBuf::msgPtr(); + rawMP = this->inBufRef.msgPtr(); this->ctx.setMsg(rawMP); // @@ -234,7 +232,8 @@ caStatus casClient::processMsg() msgsize = mp->m_postsize + sizeof(*mp); if (msgsize > bytesLeft) { - return S_cas_partialMessage; + status = S_cas_partialMessage; + break; } this->ctx.setData((void *)(rawMP+sizeof(*mp))); @@ -243,20 +242,35 @@ caStatus casClient::processMsg() this->dumpMsg(mp, (void *)(mp+1)); } + // + // Reset the context to the default + // (guarantees that previous message does not get mixed + // up with the current message) + // + this->ctx.setChannel(NULL); + this->ctx.setPV(NULL); + + // + // Check for bad protocol element + // if (mp->m_cmmd >= NELEMENTS(casClient::msgHandlers)){ - return this->uknownMessageAction (); + status = this->uknownMessageAction (); + break; } + // + // Call protocol stub + // status = (this->*casClient::msgHandlers[mp->m_cmmd]) (); if (status) { - return status; + break; } - this->inBuf::removeMsg(msgsize); - bytesLeft = this->inBuf::bytesPresent(); + this->inBufRef.removeMsg(msgsize); + bytesLeft = this->inBufRef.bytesPresent(); } - return S_cas_success; + return status; } @@ -349,7 +363,7 @@ caStatus casClient::echoAction () int status; caHdr *reply; - status = this->allocMsg(mp->m_postsize, &reply); + status = this->outBufRef.allocMsg(mp->m_postsize, &reply); if (status) { if (status==S_cas_hugeRequest) { status = sendErr(mp, ECA_TOLARGE, NULL); @@ -358,7 +372,7 @@ caStatus casClient::echoAction () } *reply = *mp; memcpy((char *) (reply+1), (char *) dp, mp->m_postsize); - this->commitMsg(); + this->outBufRef.commitMsg(); return S_cas_success; } @@ -397,7 +411,7 @@ const char *pformat, /* * allocate plenty of space for a sprintf() buffer */ - status = this->allocMsg(1024u, &reply); + status = this->outBufRef.allocMsg(1024u, &reply); if(status){ return status; } @@ -459,7 +473,7 @@ const char *pformat, size += sizeof(*curp); reply->m_postsize = size; - this->commitMsg(); + this->outBufRef.commitMsg(); return S_cas_success; } @@ -526,7 +540,7 @@ void casClient::dumpMsg(const caHdr *mp, const void *dp) char pName[64u]; char pPVName[64u]; - this->msgIO.hostNameFromAddr (pName, sizeof (pName)); + this->clientHostName (pName, sizeof (pName)); pciu = this->resIdToChannel(mp->m_cid); diff --git a/src/cas/generic/casClientIL.h b/src/cas/generic/casClientIL.h index 1a0fc2330..dc371f91a 100644 --- a/src/cas/generic/casClientIL.h +++ b/src/cas/generic/casClientIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:16 jhill + * ca server installation + * * */ @@ -37,6 +40,7 @@ #define casClientIL_h #include // caServerI inline func +#include // caServerI inline func // // find the channel associated with a resource id @@ -56,10 +60,10 @@ inline casChannelI *casClient::resIdToChannel(const caResId &id) // // casClient::getDebugLevel() // -inline unsigned casClient::getDebugLevel() -{ - return this->ctx.getServer()->getDebugLevel(); -} +//inline unsigned casClient::getDebugLevel() const +//{ +// return this->ctx.getServer()->getDebugLevel(); +//} #endif // casClientIL_h diff --git a/src/cas/generic/casCoreClient.cc b/src/cas/generic/casCoreClient.cc index 6ab0c9805..61de29543 100644 --- a/src/cas/generic/casCoreClient.cc +++ b/src/cas/generic/casCoreClient.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.3 1996/09/16 18:23:59 jhill + * vxWorks port changes + * * Revision 1.2 1996/08/13 22:53:14 jhill * changes for MVC++ * @@ -40,13 +43,29 @@ #include -#include +#include // caServerI in line func +#include // casAsyncIOI in line func +#include // casEventSys in line func +#include // casCtx in line func +#include // inBuf in line func +#include // outBuf in line func + +// +// casCoreClient::init() +// +caStatus casCoreClient::init() +{ + if (this->osiMutex::init()) { + return S_cas_noMemory; + } + return this->casEventSys::init(); +} // // static declartions for class casCoreClient // -int casCoreClient::msgHandlersInit; -pAsyncIoCallBack casCoreClient::asyncIOJumpTable[CA_PROTO_LAST_CMMD+1u]; +//int casCoreClient::msgHandlersInit; +//pAsyncIoCallBack casCoreClient::asyncIOJumpTable[CA_PROTO_LAST_CMMD+1u]; // @@ -61,9 +80,10 @@ casCoreClient::casCoreClient(caServerI &serverInternal) : casEventSys(*this) // // static member init // - casCoreClient::loadProtoJumpTable(); + //casCoreClient::loadProtoJumpTable(); } +#if 0 // // casCoreClient::loadProtoJumpTable() // @@ -93,9 +113,10 @@ void casCoreClient::loadProtoJumpTable() casCoreClient::writeNotifyResponse; casCoreClient::asyncIOJumpTable[CA_PROTO_EVENT_ADD] = casCoreClient::monitorResponse; - + casCoreClient::msgHandlersInit = TRUE; } +#endif // @@ -103,7 +124,6 @@ void casCoreClient::loadProtoJumpTable() // casCoreClient::~casCoreClient() { - tsDLIter iterIO(this->ioInProgList); casAsyncIOI *pCurIO; if (this->ctx.getServer()->getDebugLevel()>0u) { @@ -111,18 +131,19 @@ casCoreClient::~casCoreClient() } this->osiLock(); + tsDLFwdIter iterIO(this->ioInProgList); // // cancel any pending asynchronous IO // - pCurIO = iterIO(); + pCurIO = iterIO.next(); while (pCurIO) { casAsyncIOI *pNextIO; // // destructor removes from this list // - pNextIO = iterIO(); - delete pCurIO; + pNextIO = iterIO.next(); + pCurIO->destroy(); pCurIO = pNextIO; } @@ -146,7 +167,7 @@ caStatus casCoreClient::disconnectChan(caResId) return S_cas_success; } -void casCoreClient::show (unsigned level) +void casCoreClient::show (unsigned level) const { printf ("Core client\n"); this->casEventSys::show (level); @@ -158,13 +179,12 @@ void casCoreClient::show (unsigned level) // one of these for each CA request type that has // asynchronous completion // -caStatus casCoreClient::searchResponse(casChannelI *, const caHdr &, - gdd *, const caStatus) +caStatus casCoreClient::asyncSearchResponse(casDGIntfIO &, + const caAddr &, const caHdr &, const pvExistReturn &) { return S_casApp_noSupport; } -caStatus casCoreClient::createChanResponse(casChannelI *, const caHdr &, - gdd *, const caStatus) +caStatus casCoreClient::createChanResponse(const caHdr &, const pvExistReturn &) { return S_casApp_noSupport; } @@ -179,12 +199,12 @@ caStatus casCoreClient::readNotifyResponse(casChannelI *, const caHdr &, return S_casApp_noSupport; } caStatus casCoreClient::writeResponse(casChannelI *, const caHdr &, - gdd *, const caStatus) + const caStatus) { return S_casApp_noSupport; } caStatus casCoreClient::writeNotifyResponse(casChannelI *, const caHdr &, - gdd *, const caStatus) + const caStatus) { return S_casApp_noSupport; } @@ -211,28 +231,20 @@ void casCoreClient::removeChannel(casChannelI &) } // -// casCoreClient::lookupRes() -// (this shows up undefined if it is inline and compiled by g++?) +// casCoreClient::fetchRespAddr() // -casRes *casCoreClient::lookupRes(const caResId &idIn, casResType type) +caAddr casCoreClient::fetchRespAddr() { - return this->ctx.getServer()->lookupRes(idIn, type); + caAddr addr; + memset (&addr, '\0', sizeof(addr)); + return addr; } // -// casCoreClient::asyncIOCompletion() -// (this shows up undefined if it is inline and compiled by g++?) +// casCoreClient::fetchOutIntf() // -caStatus casCoreClient::asyncIOCompletion(casChannelI *pChan, - const caHdr &msg, gdd *pDesc, caStatus completionStatus) +casDGIntfIO* casCoreClient::fetchOutIntf() { - pAsyncIoCallBack pCB; - - pCB = casCoreClient::asyncIOJumpTable[msg.m_cmmd]; - if (pCB==NULL) { - return S_casApp_noSupport; - } - - return (this->*pCB)(pChan, msg, pDesc, completionStatus); + return NULL; } diff --git a/src/cas/generic/casDGClient.cc b/src/cas/generic/casDGClient.cc index 33cdc162c..10fb299b4 100644 --- a/src/cas/generic/casDGClient.cc +++ b/src/cas/generic/casDGClient.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.6 1996/09/16 18:24:00 jhill + * vxWorks port changes + * * Revision 1.5 1996/09/04 20:19:47 jhill * added missing byte swap on search reply port no * @@ -50,6 +53,12 @@ #include #include // caServerI inline func #include // casClient inline func +#include // dgOutBuf inline func +#include // dgInBuf inline func +#include // casCtx inline func +#include // inBuf inline func +#include // outBuf inline func +#include // casCoreClient inline func #include // @@ -60,9 +69,32 @@ // casDGClient::casDGClient() // casDGClient::casDGClient(caServerI &serverIn) : - casClient(serverIn, * (casDGIO *) this) + dgInBuf(*(osiMutex *)this, casDGIntfIO::optimumBufferSize()), + dgOutBuf(*(osiMutex *)this, casDGIntfIO::optimumBufferSize()), + casClient(serverIn, *this, *this), + pOutMsgIO(NULL), + pInMsgIO(NULL) { } + +// +// casDGClient::init() +// +caStatus casDGClient::init() +{ + caStatus status; + + status = this->dgInBuf::init(); + if (status) { + return status; + } + status = this->dgOutBuf::init(); + if (status) { + return status; + } + return S_cas_success; +} + // // casDGClient::destroy() // @@ -74,10 +106,12 @@ void casDGClient::destroy() // // casDGClient::show() // -void casDGClient::show(unsigned level) +void casDGClient::show(unsigned level) const { this->casClient::show(level); printf("casDGClient at %x\n", (unsigned) this); + this->dgInBuf::show(level); + this->dgOutBuf::show(level); } // @@ -87,34 +121,22 @@ caStatus casDGClient::searchAction() { const caHdr *mp = this->ctx.getMsg(); void *dp = this->ctx.getData(); - const char *pChanName = (const char *)dp; - gdd *pCanonicalName; + const char *pChanName = (const char *) dp; caStatus status; - int gddStatus; if (this->ctx.getServer()->getDebugLevel()>2u) { printf("client is searching for \"%s\"\n", pChanName); } - // - // If we cant allocate a gdd large enogh to hold the - // longest PV name then just ignore this request - // (and let the client to try again later) - // - pCanonicalName = new gddScalar(gddAppType_name, aitEnumString); - if (!pCanonicalName) { - return S_cas_success; - } - // // ask the server tool if this PV exists // - status = this->ctx.getServer()->pvExistTest(this->ctx, - pChanName, *pCanonicalName); - if (status == S_casApp_asyncCompletion) { + pvExistReturn retVal = + this->ctx.getServer()->pvExistTest(this->ctx, pChanName); + if (retVal.getStatus() == S_casApp_asyncCompletion) { status = S_cas_success; } - else if (status==S_cas_ioBlocked) { + else if (retVal.getStatus()==S_cas_ioBlocked) { // // If too many exist test IO operations are in progress // then we will just ignore this request (and wait for @@ -123,16 +145,9 @@ caStatus casDGClient::searchAction() status = S_cas_success; } else { - status = this->searchResponse(NULL, *mp, - pCanonicalName, status); + status = this->searchResponse(*mp, retVal); } - // - // delete the PV name object - // - gddStatus = pCanonicalName->unreference(); - assert(gddStatus==0); - return S_cas_success; } @@ -140,21 +155,27 @@ caStatus casDGClient::searchAction() // // caStatus casDGClient::searchResponse() // -caStatus casDGClient::searchResponse(casChannelI *nullPtr, const caHdr &msg, - gdd *pCanonicalName, const caStatus completionStatus) +caStatus casDGClient::searchResponse(const caHdr &msg, + const pvExistReturn &retVal) { caStatus status; caHdr *search_reply; unsigned short *pMinorVersion; - assert(nullPtr==NULL); - this->ctx.getServer()->pvExistTestCompletion(); // // normal search failure is ignored // - if (completionStatus==S_casApp_pvNotFound) { + if (retVal.getStatus()==S_casApp_pvNotFound) { + return S_cas_success; + } + + // + // if we dont have a virtual out msg io pointer + // then ignore the request + // + if (!this->pOutMsgIO) { return S_cas_success; } @@ -180,22 +201,25 @@ caStatus casDGClient::searchResponse(casChannelI *nullPtr, const caHdr &msg, // // check for bad parameters // - if (!pCanonicalName) { + if (retVal.getStatus()) { + errMessage(retVal.getStatus(),NULL); + return S_cas_success; + } + if (retVal.getString()) { + if (retVal.getString()[0]=='\0') { + errMessage(S_cas_badParameter, + "PV name descr is empty"); + return S_cas_success; + } + if (this->ctx.getServer()->getDebugLevel()>2u) { + printf("Search request matched for PV=\"%s\"\n", + retVal.getString()); + } + } + else { errMessage(S_cas_badParameter, "PV name descr is nill"); return S_cas_success; } - if (completionStatus) { - errMessage(completionStatus,NULL); - return S_cas_success; - } - - if (this->ctx.getServer()->getDebugLevel()>2u) { - char *pCN; - pCN = *pCanonicalName; - if (pCN) { - printf("Search request matched for PV=\"%s\"\n", pCN); - } - } /* * obtain space for the reply message @@ -205,7 +229,6 @@ caStatus casDGClient::searchResponse(casChannelI *nullPtr, const caHdr &msg, return status; } - /* * type field is abused to carry the IP * port number here CA_V44 or higher @@ -215,7 +238,7 @@ caStatus casDGClient::searchResponse(casChannelI *nullPtr, const caHdr &msg, *search_reply = msg; search_reply->m_postsize = sizeof(*pMinorVersion); search_reply->m_cid = ~0U; - search_reply->m_type = this->ctx.getServer()->serverPortNumber(); + search_reply->m_type = this->pOutMsgIO->serverPortNumber(); search_reply->m_count = 0ul; /* @@ -259,10 +282,10 @@ caStatus casDGClient::searchFailResponse(const caHdr *mp) // -// caServerI::sendBeacon() +// casDGClient::sendBeacon() // (implemented here because this has knowledge of the protocol) // -void caServerI::sendBeacon() +void casDGClient::sendBeacon(casDGIntfIO &io) { union { caHdr msg; @@ -278,16 +301,11 @@ void caServerI::sendBeacon() // // send it to all addresses on the beacon list // - this->dgClient.sendDGBeacon(buf, sizeof(msg), msg.m_available); - - // - // double the period between beacons (but dont exceed max) - // - this->advanceBeaconPeriod(); + io.sendBeacon(buf, sizeof(msg), msg.m_available); } // -// casDGClient::ioSignal() +// casDGClient::ioBlockedSignal() // void casDGClient::ioBlockedSignal() { @@ -302,53 +320,164 @@ void casDGClient::ioBlockedSignal() } // -// casDGClient::process() +// casDGClient::processDG() // -void casDGClient::process() +void casDGClient::processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO) { caStatus status; - casFlushCondition flushCond; - casFillCondition fillCond; + // + // !! special locking required here in mt case + // // // force all replies to be sent to the client // that made the request // + this->pInMsgIO = &inMsgIO; + this->pOutMsgIO = &outMsgIO; this->inBuf::clear(); this->outBuf::clear(); // // read in new input // - fillCond = this->fill(); - if (fillCond == casFillDisconnect) { - casVerify(0); - } - // - // verify that we have a message to process - // - else if (this->inBuf::bytesPresent()>0u) { - // - // process the message - // - status = this->processMsg(); - if (status) { - errMessage (status, - "unexpected error processing stateless protocol"); - } + if (this->fill() != casFillDisconnect) { + // - // force all replies to go to the sender + // verify that we have a message to process // - flushCond = this->flush(); - if (flushCond!=casFlushCompleted) { - casVerify(0); + if (this->inBuf::bytesPresent()>0u) { + this->setRecipient(this->getSender()); + + // + // process the message + // + status = this->processMsg(); + if (status) { + errMessage (status, + "unexpected error processing stateless protocol"); + } + // + // force all replies to go to the sender + // + if (this->outBuf::bytesPresent()>0u) { + casVerify (this->flush()==casFlushCompleted); + } } - } + } + // // clear the input/output buffers so replies // are always sent to the sender of the request // + this->pInMsgIO = NULL; + this->pOutMsgIO = NULL; this->inBuf::clear(); this->outBuf::clear(); } +// +// casDGClient::asyncSearchResp() +// +caStatus casDGClient::asyncSearchResponse(casDGIntfIO &outMsgIO, const caAddr &outAddr, + const caHdr &msg, const pvExistReturn &retVal) +{ + caStatus stat; + + // + // !! special locking required here in mt case + // + this->pOutMsgIO = &outMsgIO; + this->dgOutBuf::clear(); + this->setRecipient(outAddr); + + stat = this->searchResponse(msg, retVal); + + this->dgOutBuf::flush(); + this->dgOutBuf::clear(); + this->pOutMsgIO = NULL; + + return stat; +} + +// +// casDGClient::xDGSend() +// +xSendStatus casDGClient::xDGSend (char *pBufIn, bufSizeT nBytesNeedToBeSent, + bufSizeT &nBytesSent, const caAddr &recipient) +{ + xSendStatus stat; + + if (!this->pOutMsgIO) { + return xSendDisconnect; + } + stat = this->pOutMsgIO->osdSend(pBufIn, nBytesNeedToBeSent, + nBytesSent, recipient); + if (stat==xSendOK) { + // + // !! this time fetch may be slowing things down !! + // + this->elapsedAtLastSend = osiTime::getCurrent(); + } + return stat; +} + +// +// casDGClient::xDGRecv() +// +xRecvStatus casDGClient::xDGRecv (char *pBufIn, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv, caAddr &sender) +{ + xRecvStatus stat; + + if (!this->pInMsgIO) { + return xRecvDisconnect; + } + stat = this->pInMsgIO->osdRecv(pBufIn, nBytesToRecv, + nByesRecv, sender); + if (stat==xRecvOK) { + // + // !! this time fetch may be slowing things down !! + // + this->elapsedAtLastRecv = osiTime::getCurrent(); + } + return stat; +} + +// +// casDGClient::incommingBytesPresent() +// +bufSizeT casDGClient::incommingBytesPresent() const +{ + // + // !!!! perhaps this would run faster if we + // !!!! checked to see if UDP frames are in + // !!!! the queue from the same client + // + return 0u; +} + +// +// casDGClient::getDebugLevel() +// +unsigned casDGClient::getDebugLevel() const +{ + return this->getCAS().getDebugLevel(); +} + +// +// casDGClient::fetchRespAddr() +// +caAddr casDGClient::fetchRespAddr() +{ + return this->getRecipient(); +} + +// +// casDGClient::fetchOutIntf() +// +casDGIntfIO* casDGClient::fetchOutIntf() +{ + return this->pOutMsgIO; +} + diff --git a/src/cas/generic/casEventMask.cc b/src/cas/generic/casEventMask.cc index ce2cada67..f7d1515a0 100644 --- a/src/cas/generic/casEventMask.cc +++ b/src/cas/generic/casEventMask.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/09/04 20:20:44 jhill + * removed sizeof(casEventMask::mask) for MSVISC++ + * * Revision 1.1.1.1 1996/06/20 00:28:16 jhill * ca server installation * @@ -40,8 +43,7 @@ #include #include -#include -#include +#include #ifdef TEST main () @@ -86,6 +88,23 @@ main () } #endif +// +// casEventRegistry::init() +// +int casEventRegistry::init() +{ + if (!this->hasBeenInitialized) { + int status; + status = this->resTable :: + init(1u<<8u); + if (status==0) { + this->hasBeenInitialized = 1u; + } + return status; + } + return 0; +} + // // casEventRegistry::maskAllocator() @@ -94,15 +113,16 @@ inline casEventMask casEventRegistry::maskAllocator() { casEventMask evMask; - if (this->allocator>=CHAR_BIT*sizeof(evMask.mask)) { - return evMask; + this->mutex.osiLock(); + if (this->allocatorallocator++); } - evMask.mask = 1u<<(this->allocator++); + this->mutex.osiUnlock(); return evMask; } // -// casEventMask::registerEvent() +// casEventRegistry::registerEvent() // casEventMask casEventRegistry::registerEvent(const char *pName) { @@ -111,29 +131,38 @@ casEventMask casEventRegistry::registerEvent(const char *pName) int stat; casEventMask mask; - if (!this->init) { - errMessage(S_cas_noMemory, "no memory during init?"); + if (!this->hasBeenInitialized) { + errMessage(S_cas_noMemory, + "casEventRegistry: not initialized?"); return mask; } + this->mutex.osiLock(); pEntry = this->lookup (id); if (pEntry) { - return *pEntry; + mask = *pEntry; } - mask = this->maskAllocator(); - if (mask.mask == 0u) { - errMessage(S_cas_tooManyEvents, NULL); - return mask; + else { + mask = this->maskAllocator(); + if (mask.mask == 0u) { + errMessage(S_cas_tooManyEvents, NULL); + } + else { + pEntry = new casEventMaskEntry(mask, pName); + if (pEntry) { + stat = this->add(*pEntry); + assert(stat==0); + mask = *pEntry; + } + else { + mask.mask = 0u; + errMessage(S_cas_noMemory, + "mask bit was lost during init"); + } + } } - pEntry = new casEventMaskEntry(mask, pName); - if (!pEntry) { - mask.mask = 0u; - errMessage(S_cas_noMemory, "mask bit was lost during init"); - return mask; - } - stat = this->add(*pEntry); - assert(stat==0); - return *pEntry; + this->mutex.osiUnlock(); + return mask; } // @@ -146,15 +175,25 @@ void casEventMask::show(unsigned level) } } +casEventMask::casEventMask (casEventRegistry ®, const char *pName) +{ + *this = reg.registerEvent (pName); +} + // // casEventRegistry::show() // void casEventRegistry::show(unsigned level) { + if (!this->hasBeenInitialized) { + printf ("casEventRegistry: not initialized\n"); + } + this->mutex.osiLock(); if (level>1u) { - printf ("init = %d bit allocator = %d\n", - this->init, this->allocator); + printf ("casEventRegistry: bit allocator = %d\n", + this->allocator); } this->resTable ::show(level); + this->mutex.osiUnlock(); } diff --git a/src/cas/generic/casEventMask.h b/src/cas/generic/casEventMask.h index d832e1e0b..1fa37a9a2 100644 --- a/src/cas/generic/casEventMask.h +++ b/src/cas/generic/casEventMask.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:16 jhill + * ca server installation + * * */ @@ -36,7 +39,7 @@ #ifndef casEventMaskH #define casEventMaskH -#include +#include "resourceLib.h" class casEventMaskEntry; @@ -97,38 +100,6 @@ public: private: }; -class casEventRegistry : resTable { -public: - casEventRegistry() : allocator(0) - { - int status; - status = this->resTable ::init(1u<<8u); - if (status) { - this->init = 0u; - return; - } - this->init = 1u; - } - ~casEventRegistry() - { - this->destroyAllEntries(); - } - casEventMask registerEvent (const char *pName); - - void show (unsigned level); - -private: - unsigned allocator; - unsigned char init; - - casEventMask maskAllocator(); -}; - -inline casEventMask::casEventMask (casEventRegistry ®, const char *pName) -{ - *this = reg.registerEvent (pName); -} - inline casEventMask operator| (const casEventMask &lhs, const casEventMask &rhs) { casEventMask result; diff --git a/src/cas/generic/casEventSys.cc b/src/cas/generic/casEventSys.cc index 7d84d5aa0..871ad1c8a 100644 --- a/src/cas/generic/casEventSys.cc +++ b/src/cas/generic/casEventSys.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.3 1996/09/16 18:24:01 jhill + * vxWorks port changes + * * Revision 1.2 1996/07/24 22:00:49 jhill * added pushOnToEventQueue() * @@ -49,19 +52,10 @@ #include #include // casMonitor inline func -#if 0 -VERSIONID(caEventQueuec,"%W% %G%") -#endif - -#if 0 -#include -#endif - - // // casEventSys::show() // -void casEventSys::show(unsigned level) +void casEventSys::show(unsigned level) const { printf ("casEventSys at %x\n", (unsigned) this); if (level>=1u) { diff --git a/src/cas/generic/casEventSysIL.h b/src/cas/generic/casEventSysIL.h index 1ac47f25f..ac5bd8e20 100644 --- a/src/cas/generic/casEventSysIL.h +++ b/src/cas/generic/casEventSysIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/09/16 18:24:02 jhill + * vxWorks port changes + * * Revision 1.1.1.1 1996/06/20 00:28:16 jhill * ca server installation * @@ -39,6 +42,33 @@ #ifndef casEventSysIL_h #define casEventSysIL_h +// +// required for casCoreClient::lookupRes() +// +#include "casCoreClientIL.h" + +// +// casEventSys::casEventSys () +// +inline casEventSys::casEventSys (casCoreClient &coreClientIn) : + coreClient(coreClientIn), + numEventBlocks(0u), + maxLogEntries(individualEventEntries), + eventsOff(aitFalse) +{ +} + +// +// casEventSys::init() +// +inline caStatus casEventSys::init() +{ + if (mutex.init()) { + return S_cas_noMemory; + } + return S_cas_success; +} + // // casEventSys::addToEventQueue() // @@ -53,6 +83,81 @@ inline void casEventSys::addToEventQueue(casEvent &event) this->coreClient.eventSignal(); } +// +// casEventSys::getCoreClient +// +inline casCoreClient &casEventSys::getCoreClient() +{ + return this->coreClient; +} + +// +// casEventSys::getEventsOff () +// +inline aitBool casEventSys::getEventsOff () const +{ + return this->eventsOff?aitTrue:aitFalse; +} + +// +// casEventSys::setEventsOn() +// +void casEventSys::setEventsOn() +{ + this->eventsOff = aitFalse; +} + +// +// casEventSys::setEventsOff() +// +void casEventSys::setEventsOff() +{ + this->eventsOff = aitTrue; +} + +// +// casEventSys::insertEventQueue() +// +inline void casEventSys::insertEventQueue(casEvent &insert, casEvent &prevEvent) +{ + this->mutex.osiLock(); + this->eventLogQue.insertAfter(insert, prevEvent); + this->mutex.osiUnlock(); +} + +// +// casEventSys::pushOnToEventQueue() +// +inline void casEventSys::pushOnToEventQueue(casEvent &event) +{ + this->mutex.osiLock(); + this->eventLogQue.push(event); + this->mutex.osiUnlock(); +} + +// +// casEventSys::removeFromEventQueue() +// +inline void casEventSys::removeFromEventQueue(casEvent &event) +{ + this->mutex.osiLock(); + this->eventLogQue.remove(event); + this->mutex.osiUnlock(); +} + +// +// casEventSys::full() +// +inline aitBool casEventSys::full() +{ + if (this->eventLogQue.count()>=this->maxLogEntries) { + return aitTrue; + } + else { + return aitFalse; + } +} + // // casMonitor::resIdToMon() // diff --git a/src/cas/generic/casInternal.h b/src/cas/generic/casInternal.h index 74bc33570..b6279279a 100644 --- a/src/cas/generic/casInternal.h +++ b/src/cas/generic/casInternal.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.7 1996/09/16 18:24:02 jhill + * vxWorks port changes + * * Revision 1.6 1996/09/04 20:21:41 jhill * removed operator -> and added member pv * @@ -53,9 +56,9 @@ // // EPICS // -#include -#include -#include +#include "tsDLList.h" +#include "resourceLib.h" +#include "caProto.h" typedef aitUint32 caResId; @@ -67,7 +70,7 @@ class casChannelI; // class casEvent : public tsDLNode { public: - virtual ~casEvent() {} + virtual ~casEvent(); virtual caStatus cbFunc(casEventSys &)=0; private: }; @@ -85,12 +88,15 @@ enum casResType {casChanT=1, casClientMonT, casPVT}; class casRes : public uintRes { public: - virtual ~casRes() {} + virtual ~casRes(); virtual casResType resourceType() const = 0; virtual void show (unsigned level) = 0; private: }; +class ioBlockedList; +class osiMutex; + // // ioBlocked // @@ -98,89 +104,24 @@ class ioBlocked : public tsDLNode { friend class ioBlockedList; public: ioBlocked (); - virtual ~ioBlocked (); - void setBlocked (ioBlockedList &list); + virtual ~ioBlocked ()=0; private: ioBlockedList *pList; - virtual void ioBlockedSignal () = 0; + virtual void ioBlockedSignal (); }; // // ioBlockedList // -class ioBlockedList : public tsDLList { -friend class ioBlocked; +class ioBlockedList : private tsDLList { public: - ~ioBlockedList (); - void signal (); + ioBlockedList (); + ~ioBlockedList (); + void signal (); + void removeItemFromIOBLockedList(ioBlocked &item); + void addItemToIOBLockedList(ioBlocked &item); }; - - -// -// ioBlockedList::~ioBlockedList () -// -inline ioBlockedList::~ioBlockedList () -{ - ioBlocked *pB; - while ( (pB = this->get ()) ) { - pB->pList = NULL; - } -} - -// -// ioBlockedList::signal () -// -// works from a temporary list to avoid problems -// where the virtual function adds items to the -// list -// -inline void ioBlockedList::signal () -{ - tsDLList tmp(*this); - ioBlocked *pB; - - while ( (pB = tmp.get ()) ) { - pB->pList = NULL; - pB->ioBlockedSignal (); - } -} - -// -// ioBlocked::ioBlocked () -// -inline ioBlocked::ioBlocked() : pList (NULL) -{ -} - -// -// ioBlocked::~ioBlocked () -// -inline ioBlocked::~ioBlocked () -{ - if (this->pList) { - this->pList->remove (*this); - this->pList = NULL; - } -} - -// -// ioBlocked::setBlocked () -// -inline void ioBlocked::setBlocked (ioBlockedList &list) -{ - if (!this->pList) { - this->pList = &list; - list.add (*this); - } - else { - // - // requests to be in more than one - // list at at time are fatal - // - assert (&list == this->pList); - } -} - + class casMonitor; // @@ -192,50 +133,25 @@ public: // only used when this part of another structure // (and we need to postpone true construction) // - casMonEvent () : pValue(NULL), id(0u) {} - casMonEvent (casMonitor &monitor, gdd &newValue); - casMonEvent (casMonEvent &initValue); + inline casMonEvent (); + inline casMonEvent (casMonitor &monitor, gdd &newValue); + inline casMonEvent (casMonEvent &initValue); // // ~casMonEvent () // - ~casMonEvent (); + inline ~casMonEvent (); caStatus cbFunc(casEventSys &); // // casMonEvent::getValue() // - gdd *getValue() const - { - return this->pValue; - } + inline gdd *getValue() const; - void operator = (class casMonEvent &monEventIn) - { - int gddStatus; - if (this->pValue) { - gddStatus = this->pValue->unreference(); - assert (!gddStatus); - } - if (monEventIn.pValue) { - gddStatus = monEventIn.pValue->reference(); - assert (!gddStatus); - } - this->pValue = monEventIn.pValue; - this->id = monEventIn.id; - } + inline void operator = (class casMonEvent &monEventIn); - void clear() - { - int gddStatus; - if (this->pValue) { - gddStatus = this->pValue->unreference(); - assert (!gddStatus); - this->pValue = NULL; - } - this->id = 0u; - } + inline void clear(); void assign (casMonitor &monitor, gdd *pValueIn); private: @@ -243,7 +159,6 @@ private: caResId id; }; -class osiMutex; // // casMonitor() @@ -330,79 +245,169 @@ inline void casMonitor::post(const casEventMask &select, gdd &value) } +class caServer; class casCoreClient; -class casAsyncIO; class casChannelI; class casCtx; class caServer; +class casAsyncIO; +class casAsyncReadIO; +class casAsyncWriteIO; +class casAsyncPVExistIO; -// -// casAsyncIOI -// -// (server internal asynchronous IO class) -// -// -// Operations may be completed asynchronously -// by the server tool if the virtual function creates a -// casAsyncIO object and returns the status code -// S_casApp_asyncCompletion -// class casAsyncIOI : public casEvent, public tsDLNode { public: - casAsyncIOI(const casCtx &ctx, casAsyncIO &ioIn, gdd *pDD=NULL); + casAsyncIOI (casCoreClient &client, casAsyncIO &ioExternal); virtual ~casAsyncIOI(); // // place notification of IO completion on the event queue // - caStatus postIOCompletion(caStatus completionStatus, gdd *pDesc=NULL); - - caServer *getCAS(); - - inline casAsyncIO * operator -> (); - - void setServerDelete() - { - this->serverDelete = 1u; - } + caStatus postIOCompletionI(); inline void lock(); inline void unlock(); - gdd *getValuePtr () - { - return this->pDesc; - } + virtual caStatus cbFuncAsyncIO()=0; + virtual int readOP(); + + void destroyIfReadOP(); + + caServer *getCAS(); + + inline void destroy(); + + void reportInvalidAsynchIO(unsigned); + +protected: + casCoreClient &client; + casAsyncIO &ioExternal; - void clrValue () - { - if (this->pDesc) { - gddStatus status; - status = this->pDesc->unreference(); - assert(!status); - this->pDesc = NULL; - } - } private: + unsigned inTheEventQueue:1; + unsigned posted:1; + unsigned ioComplete:1; + unsigned serverDelete:1; // // casEvent virtual call back function // (called when IO completion event reaches top of event queue) // caStatus cbFunc(casEventSys &); - caHdr const msg; - casCoreClient &client; - casAsyncIO &asyncIO; - casChannelI *pChan; // optional - gdd *pDesc; // optional - caStatus completionStatus; - unsigned inTheEventQueue:1; - unsigned posted:1; - unsigned ioComplete:1; - unsigned serverDelete:1; + inline casAsyncIO * operator -> (); +}; + +// +// casAsyncRdIOI +// +// (server internal asynchronous read IO class) +// +class casAsyncRdIOI : public casAsyncIOI { +public: + casAsyncRdIOI(const casCtx &ctx, casAsyncReadIO &ioIn); + virtual ~casAsyncRdIOI(); + + void destroyIfReadOP(); + + caStatus cbFuncAsyncIO(); + casAsyncIO &getAsyncIO(); + + caStatus postIOCompletion(caStatus completionStatus, + gdd &valueRead); + int readOP(); +private: + caHdr const msg; + casChannelI &chan; + gdd *pDD; + caStatus completionStatus; +}; + +// +// casAsyncWtIOI +// +// (server internal asynchronous write IO class) +// +class casAsyncWtIOI : public casAsyncIOI { +public: + casAsyncWtIOI(const casCtx &ctx, casAsyncWriteIO &ioIn); + virtual ~casAsyncWtIOI(); + + // + // place notification of IO completion on the event queue + // + caStatus postIOCompletion(caStatus completionStatus); + + caStatus cbFuncAsyncIO(); + casAsyncIO &getAsyncIO(); +private: + caHdr const msg; + casChannelI &chan; + caStatus completionStatus; +}; + +union ca_addr; + +// +// casOpaqueAddr +// +// store address as an opaque array of bytes so that +// we dont drag the socket (or other IO specific) +// headers into the server tool. +// +// +// get() will assert fail if the init flag has not been +// set +// +class casOpaqueAddr +{ +public: + inline casOpaqueAddr(); + inline void clear(); + inline int hasBeenInitialized() const; + inline casOpaqueAddr (const union ca_addr &addr); + inline void set (const union ca_addr &); + inline union ca_addr get () const; +private: + char opaqueAddr[16u]; // large enough for socket addresses + char init; + + // + // simple class that will assert fail if + // sizeof(opaqueAddr) < sizeof(caAddr) + // + class checkSize { + public: + checkSize(); + }; + static checkSize sizeChecker; +}; + +class casDGIntfIO; + +// +// casAsyncExIOI +// +// (server internal asynchronous read IO class) +// +class casAsyncExIOI : public casAsyncIOI { +public: + casAsyncExIOI(const casCtx &ctx, casAsyncPVExistIO &ioIn); + virtual ~casAsyncExIOI(); + + // + // place notification of IO completion on the event queue + // + caStatus postIOCompletion(const pvExistReturn &retVal); + + caStatus cbFuncAsyncIO(); + casAsyncIO &getAsyncIO(); +private: + caHdr const msg; + pvExistReturn retVal; + casDGIntfIO * const pOutDGIntfIO; + const casOpaqueAddr dgOutAddr; }; -class casCoreClient; class casChannel; class casPVI; @@ -468,6 +473,8 @@ public: inline casChannel * operator -> (); + void clearOutstandingReads(); + protected: tsDLList monitorList; tsDLList ioInProgList; @@ -511,8 +518,6 @@ public: // caServerI &getCAS() {return this->cas;} - static caStatus verifyPVName(gdd &name); - // // CA only does 1D arrays for now (and the new server // temporarily does only scalers) @@ -574,3 +579,46 @@ private: inline void unlock(); }; +// +// inline functions associated with the return arg from +// caServer::pvExistTest() +// +inline pvExistReturn::pvExistReturn(caStatus status, + char* pCanonicalNameStr) : + stat(status), str(pCanonicalNameStr) +{ +} +inline pvExistReturn::pvExistReturn(caStatus status, + const char* pCanonicalNameStr) : + stat(status), str(pCanonicalNameStr) +{ +} +inline pvExistReturn::pvExistReturn(pvExistReturn &init) : + stat(init.stat), str(init.str) +{ +} +inline pvExistReturn::pvExistReturn(const pvExistReturn &init) : + stat(init.stat), str(init.str) +{ +} +inline const caStatus pvExistReturn::getStatus() const +{ + return this->stat; +} +inline const char* pvExistReturn::getString() const +{ + return str.string(); +} +inline pvExistReturn& pvExistReturn::operator=(pvExistReturn &rhs) +{ + this->stat = rhs.stat; + this->str = rhs.str; + return *this; +} +inline pvExistReturn& pvExistReturn::operator=(const pvExistReturn &rhs) +{ + this->stat = rhs.stat; + this->str = rhs.str; + return *this; +} + diff --git a/src/cas/generic/casMonEvent.cc b/src/cas/generic/casMonEvent.cc index a134bf602..351625d7b 100644 --- a/src/cas/generic/casMonEvent.cc +++ b/src/cas/generic/casMonEvent.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/06/26 21:18:55 jhill + * now matches gdd api revisions + * * Revision 1.1.1.1 1996/06/20 00:28:16 jhill * ca server installation * @@ -37,41 +40,9 @@ #include -#include - -// -// casMonEvent::casMonEvent() -// -casMonEvent::casMonEvent (casMonitor &monitor, gdd &newValue) : - pValue(&newValue), - id(monitor.casRes::getId()) -{ - int gddStatus; - gddStatus = this->pValue->reference(); - assert (!gddStatus); -} - -// -// casMonEvent::casMonEvent() -// -casMonEvent::casMonEvent (casMonEvent &initValue) : - pValue(initValue.pValue), - id(initValue.id) -{ - int gddStatus; - if (this->pValue) { - gddStatus = this->pValue->reference(); - assert (!gddStatus); - } -} - -// -// ~casMonEvent () -// -casMonEvent::~casMonEvent () -{ - this->clear(); -} +#include // casEventSys in line func +#include // casMonEvent in line func +#include // casCtx in line func // // casMonEvent::cbFunc() diff --git a/src/cas/generic/casMonEventIL.h b/src/cas/generic/casMonEventIL.h index f8988ecce..5b2600709 100644 --- a/src/cas/generic/casMonEventIL.h +++ b/src/cas/generic/casMonEventIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:16 jhill + * ca server installation + * * */ @@ -42,6 +45,85 @@ // undefined // +// +// casMonEvent::casMonEvent() +// +inline casMonEvent::casMonEvent () : + pValue(NULL), id(0u) {} + +// +// casMonEvent::casMonEvent() +// +inline casMonEvent::casMonEvent (casMonitor &monitor, gdd &newValue) : + pValue(&newValue), + id(monitor.casRes::getId()) +{ + int gddStatus; + gddStatus = this->pValue->reference(); + assert (!gddStatus); +} + +// +// casMonEvent::casMonEvent() +// +inline casMonEvent::casMonEvent (casMonEvent &initValue) : + pValue(initValue.pValue), + id(initValue.id) +{ + int gddStatus; + if (this->pValue) { + gddStatus = this->pValue->reference(); + assert (!gddStatus); + } +} + +// +// casMonEvent::operator = () +// +inline void casMonEvent::operator = (class casMonEvent &monEventIn) +{ + int gddStatus; + if (this->pValue) { + gddStatus = this->pValue->unreference(); + assert (!gddStatus); + } + if (monEventIn.pValue) { + gddStatus = monEventIn.pValue->reference(); + assert (!gddStatus); + } + this->pValue = monEventIn.pValue; + this->id = monEventIn.id; +} + +// +// casMonEvent::clear() +// +inline void casMonEvent::clear() +{ + int gddStatus; + if (this->pValue) { + gddStatus = this->pValue->unreference(); + assert (!gddStatus); + this->pValue = NULL; + } + this->id = 0u; +} + +// +// ~casMonEvent () +// +inline casMonEvent::~casMonEvent () +{ + this->clear(); +} + +// +// casMonEvent::getValue() +// +inline gdd *casMonEvent::getValue() const +{ + return this->pValue; +} #endif // casMonEventIL_h diff --git a/src/cas/generic/casMonitor.cc b/src/cas/generic/casMonitor.cc index e38c16256..14b9d3df7 100644 --- a/src/cas/generic/casMonitor.cc +++ b/src/cas/generic/casMonitor.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.5 1996/09/16 18:24:03 jhill + * vxWorks port changes + * * Revision 1.4 1996/07/24 22:00:49 jhill * added pushOnToEventQueue() * @@ -49,6 +52,7 @@ #include // casChannelI inline func #include // casEventSys inline func #include // casMonEvent inline func +#include // casCtx inline func // diff --git a/src/cas/generic/casMsgIO.cc b/src/cas/generic/casMsgIO.cc index 7f2391898..6966a8002 100644 --- a/src/cas/generic/casMsgIO.cc +++ b/src/cas/generic/casMsgIO.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1996/09/16 18:24:04 jhill + * vxWorks port changes + * * Revision 1.1.1.1 1996/06/20 00:28:15 jhill * ca server installation * @@ -40,6 +43,61 @@ #include +class casMsgIO { +public: + casMsgIO(); + virtual ~casMsgIO(); + + osiTime timeOfLastXmit() const; + osiTime timeOfLAstRecv() const; + + // + // show status of IO subsystem + // (cant be const because a lock is taken) + // + void show (unsigned level) const; + + // + // io independent send/recv + // + xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent, + const caAddr &addr); + xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv, caAddr &addr); + + virtual bufSizeT incommingBytesPresent() const; + virtual casIOState state() const=0; + virtual void clientHostName (char *pBuf, unsigned bufSize) const =0; + virtual int getFD() const; + void setNonBlocking() + { + this->xSetNonBlocking(); + this->blockingStatus = xIsntBlocking; + } + + // + // The server's port number + // (to be used for connection requests) + // + virtual unsigned serverPortNumber()=0; +private: + // + // private data members + // + osiTime elapsedAtLastSend; + osiTime elapsedAtLastRecv; + xBlockingStatus blockingStatus; + + virtual xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual, const caAddr &addr) =0; + virtual xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual, caAddr &addr) =0; + virtual void osdShow (unsigned level) const = 0; + virtual void xSetNonBlocking(); +}; + + casMsgIO::casMsgIO() { this->elapsedAtLastSend = this->elapsedAtLastRecv @@ -53,9 +111,9 @@ casMsgIO::~casMsgIO() // -// casMsgIO::show(unsigned level) +// casMsgIO::show(unsigned level) const // -void casMsgIO::show(unsigned level) +void casMsgIO::show(unsigned level) const { osiTime elapsed; osiTime current; @@ -74,19 +132,27 @@ void casMsgIO::show(unsigned level) } } -xRecvStatus casMsgIO::xRecv(char *pBuf, bufSizeT nBytes, bufSizeT &nActualBytes) +// +// casMsgIO::xRecv() +// +xRecvStatus casMsgIO::xRecv(char *pBuf, bufSizeT nBytes, + bufSizeT &nActualBytes, caAddr &from) { xRecvStatus stat; - stat = this->osdRecv(pBuf, nBytes, nActualBytes); + stat = this->osdRecv(pBuf, nBytes, nActualBytes, from); if (stat==xRecvOK) { this->elapsedAtLastRecv = osiTime::getCurrent(); } return stat; } +// +// casMsgIO::xSend() +// xSendStatus casMsgIO::xSend(char *pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nActualBytes) + bufSizeT nBytesNeedToBeSent, bufSizeT &nActualBytes, + const caAddr &to) { xSendStatus stat; bufSizeT nActualBytesDelta; @@ -96,7 +162,7 @@ xSendStatus casMsgIO::xSend(char *pBuf, bufSizeT nBytesAvailableToSend, nActualBytes = 0u; if (this->blockingStatus == xIsntBlocking) { stat = this->osdSend(pBuf, nBytesAvailableToSend, - nActualBytes); + nActualBytes, to); if (stat == xSendOK) { this->elapsedAtLastSend = osiTime::getCurrent(); } @@ -105,7 +171,7 @@ xSendStatus casMsgIO::xSend(char *pBuf, bufSizeT nBytesAvailableToSend, while (nBytesNeedToBeSent) { stat = this->osdSend(pBuf, nBytesAvailableToSend, - nActualBytesDelta); + nActualBytesDelta, to); if (stat != xSendOK) { return stat; } @@ -122,13 +188,7 @@ xSendStatus casMsgIO::xSend(char *pBuf, bufSizeT nBytesAvailableToSend, return xSendOK; } -void casMsgIO::sendBeacon(char & /*msg*/, bufSizeT /*length*/, - aitUint32 &/*m_avail*/) -{ - printf("virtual base sendBeacon() called?\n"); -} - -int casMsgIO::getFileDescriptor() const +int casMsgIO::getFD() const { return -1; // some os will not have file descriptors } diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index c1f0f6563..f168a6450 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.3 1996/07/01 19:56:12 jhill + * one last update prior to first release + * * Revision 1.2 1996/06/21 02:30:53 jhill * solaris port * @@ -47,6 +50,7 @@ #include #include // casPVI inline func +#include // casCtx inline func casPV::casPV (const casCtx &ctx, const char * const pPVName) : casPVI (*ctx.getServer(), pPVName, *this) diff --git a/src/cas/generic/casPVI.cc b/src/cas/generic/casPVI.cc index 4d4e4b2eb..4d2a9dcc8 100644 --- a/src/cas/generic/casPVI.cc +++ b/src/cas/generic/casPVI.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.4 1996/09/04 20:23:17 jhill + * init new member cas and add arg to serverToolDebug() + * * Revision 1.3 1996/07/01 19:56:13 jhill * one last update prior to first release * @@ -42,9 +45,9 @@ */ -#include -#include // casPVI inline func -#include // caServerI inline func +#include "server.h" +#include "casPVIIL.h" // casPVI inline func +#include "caServerIIL.h" // caServerI inline func // @@ -71,64 +74,32 @@ casPVI::~casPVI() { casPVListChan *pChan; casPVListChan *pNextChan; - tsDLIter iter(this->chanList); this->lock(); // // delete any attached channels // - pChan = iter(); + tsDLFwdIter iter(this->chanList); + pChan = iter.next(); while (pChan) { // // deleting the channel removes it from the list // - pNextChan = iter(); + pNextChan = iter.next(); (*pChan)->destroy(); pChan = pNextChan; } this->cas.removePV(*this); - casVerify (this->nIOAttached==0u); - this->unlock(); -} -// -// caPVI::verifyPVName() -// -caStatus casPVI::verifyPVName(gdd &name) -{ - int gddStatus; - - // - // verify up front that they have supplied - // a valid name (so that we wont fail - // in the PV constructor) - // - gddStatus = name.reference(); - if (gddStatus) { - serverToolDebug("GDD PV name must not be \"no ref\""); - return S_cas_badPVName; - } - gddStatus = name.unreference(); - if (gddStatus) { - serverToolDebug("corruption expected"); - return S_cas_badPVName; - } - - if (name.primitiveType() != aitEnumString) { - serverToolDebug("GDD PV name must be stored as an aitString"); - return S_cas_badPVName; - } - - if (name.dimension() != 0u) { - serverToolDebug("GDD Dimension must be zero (gddScaler)"); - return S_cas_badPVName; - } - - return S_cas_success; + // + // all outstanding IO should have been deleted + // when we destroyed the channels + // + casVerify (this->nIOAttached==0u); } diff --git a/src/cas/generic/casPVIIL.h b/src/cas/generic/casPVIIL.h index f17d1646d..a7fcbbbe3 100644 --- a/src/cas/generic/casPVIIL.h +++ b/src/cas/generic/casPVIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.6 1996/09/16 18:24:05 jhill + * vxWorks port changes + * * Revision 1.5 1996/09/04 20:23:59 jhill * added operator -> * @@ -51,7 +54,7 @@ #ifndef casPVIIL_h #define casPVIIL_h -#include +#include "dbMapper.h" // @@ -219,10 +222,12 @@ inline void casPVI::postEvent (const casEventMask &select, gdd &event) // event.markConstant(); - tsDLIter iter(this->chanList); - while ( (pChan = iter()) ) { + this->lock(); + tsDLFwdIter iter(this->chanList); + while ( (pChan = iter.next()) ) { pChan->postEvent(select, event); } + this->unlock(); } #endif // casPVIIL_h diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index 89c9c3436..a2f4b2c41 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.10 1996/09/16 18:24:05 jhill + * vxWorks port changes + * * Revision 1.9 1996/09/04 20:25:53 jhill * use correct app type for exist test gdd, correct byte * oder for mon mask, and efficient use of PV name gdd @@ -57,14 +60,18 @@ * */ -#include -#include // ait to dbr types -#include // EPICS application type table -#include // caServerI inline functions -#include // casClient inline functions -#include // casChannelI inline functions -#include // casPVI inline functions -#include +#include "server.h" +#include "dbMapper.h" // ait to dbr types +#include "gddAppTable.h" // EPICS application type table +#include "caServerIIL.h" // caServerI inline functions +#include "casClientIL.h" // casClient inline functions +#include "casChannelIIL.h" // casChannelI inline functions +#include "casPVIIL.h" // casPVI inline functions +#include "casCtxIL.h" // casCtx inline functions +#include "casEventSysIL.h" // casEventSys inline functions +#include "inBufIL.h" // inBuf inline functions +#include "outBufIL.h" // outBuf inline functions +#include "gddApps.h" VERSIONID(casStrmClientcc,"%W% %G%") @@ -105,7 +112,7 @@ caStatus casStrmClient::verifyRequest (casChannelI *&pChan) // request. // if (pChan->getPVI().okToBeginNewIO()!=aitTrue) { - this->ioBlocked::setBlocked (pChan->getPVI()); + pChan->getPVI().addItemToIOBLockedList(*this); return S_cas_ioBlocked; } else { @@ -120,35 +127,31 @@ caStatus casStrmClient::verifyRequest (casChannelI *&pChan) inline caStatus casStrmClient::createChannel (const char *pName) { caStatus status; - int gddStatus; - gdd *pCanonicalName; - - pCanonicalName = new gddScalar(gddAppType_name, aitEnumString); - if (!pCanonicalName) { - return S_cas_noMemory; - } /* * Verify that the server still has this channel - * and that we have its correct official name. + * and that we have it's correct official name. * I assume that we may have found this server by * contacting a name resolution service so we need to * verify that the specified channel still exists here. */ - status = this->ctx.getServer()->pvExistTest( - this->ctx, pName, *pCanonicalName); - if (status == S_casApp_asyncCompletion) { + pvExistReturn retVal = + this->ctx.getServer()->pvExistTest(this->ctx, pName); + if (retVal.getStatus() == S_casApp_asyncCompletion) { status = S_cas_success; } - else if (status == S_cas_ioBlocked) { - this->ioBlocked::setBlocked (this->getCAS()); + else if (retVal.getStatus() == S_cas_ioBlocked) { + this->ctx.getServer()->addItemToIOBLockedList(*this); + status = S_cas_ioBlocked; } else { - status = createChanResponse (NULL, *this->ctx.getMsg(), - pCanonicalName, status); + // + // All use of the string in retVal below ends up getting + // copied (not referenced) so we are ok if they wrap + // pName through into retVal + // + status = createChanResponse (*this->ctx.getMsg(), retVal); } - gddStatus = pCanonicalName->unreference (); - assert (!gddStatus); return status; } @@ -157,15 +160,13 @@ inline caStatus casStrmClient::createChannel (const char *pName) // // casStrmClient::casStrmClient() // -casStrmClient::casStrmClient(caServerI &serverInternal, casMsgIO &ioIn) : - casClient(serverInternal, ioIn) +casStrmClient::casStrmClient(caServerI &serverInternal) : + inBuf(*(osiMutex *)this, casStreamIO::optimumBufferSize()), + outBuf(*(osiMutex *)this, casStreamIO::optimumBufferSize()), + casClient(serverInternal, *this, *this), + pUserName(NULL), pHostName(NULL) { - assert(&ioIn); this->ctx.getServer()->installClient(this); - - this->pUserName = NULL; - this->pHostName = NULL; - this->ioBlockCache = NULL; } // @@ -175,10 +176,21 @@ caStatus casStrmClient::init() { caStatus status; + // + // call base class initializers + // status = casClient::init(); if (status) { return status; } + status = this->inBuf::init(); + if (status) { + return status; + } + status = this->outBuf::init(); + if (status) { + return status; + } this->pHostName = new char [1u]; if (!this->pHostName) { @@ -203,7 +215,8 @@ casStrmClient::~casStrmClient() { casChannelI *pChan; casChannelI *pNextChan; - tsDLIter iter(this->chanList); + + this->osiLock(); // // remove this from the list of connected clients @@ -217,13 +230,12 @@ casStrmClient::~casStrmClient() if (this->pHostName) { delete [] this->pHostName; } - - this->osiLock(); // // delete all channel attached // - pChan = iter(); + tsDLFwdIter iter(this->chanList); + pChan = iter.next(); while (pChan) { // // destroying the channel removes it from the list @@ -233,8 +245,6 @@ casStrmClient::~casStrmClient() pChan = pNextChan; } - delete &this->msgIO; - this->osiUnlock(); } @@ -257,13 +267,15 @@ inline casClientMon *caServerI::resIdToClientMon(const caResId &idIn) // // casStrmClient::show (unsigned level) // -void casStrmClient::show (unsigned level) +void casStrmClient::show (unsigned level) const { this->casClient::show (level); printf ("casStrmClient at %x\n", (unsigned) this); if (level > 1u) { printf ("\tuser %s at %s\n", this->pUserName, this->pHostName); } + this->inBuf::show(level); + this->outBuf::show(level); } @@ -693,15 +705,10 @@ caStatus casStrmClient::writeAction() // casStrmClient::writeResponse() // caStatus casStrmClient::writeResponse (casChannelI *, - const caHdr &msg, gdd *pDesc, const caStatus completionStatus) + const caHdr &msg, const caStatus completionStatus) { caStatus status; - if (pDesc) { - errMessage(S_cas_badParameter, - "didnt expect a data descriptor from asynch write"); - } - if (completionStatus) { errMessage(completionStatus, NULL); status = this->sendErrWithEpicsStatus(&msg, @@ -734,7 +741,7 @@ caStatus casStrmClient::writeNotifyAction() // if ((*pChan)->writeAccess()!=aitTrue) { return casStrmClient::writeNotifyResponse(pChan, *mp, - NULL, S_cas_noWrite); + S_cas_noWrite); } // @@ -746,7 +753,7 @@ caStatus casStrmClient::writeNotifyAction() } else { status = casStrmClient::writeNotifyResponse(pChan, *mp, - NULL, status); + status); } return status; @@ -757,16 +764,11 @@ caStatus casStrmClient::writeNotifyAction() * casStrmClient::writeNotifyResponse() */ caStatus casStrmClient::writeNotifyResponse(casChannelI *, - const caHdr &msg, gdd *pDesc, const caStatus completionStatus) + const caHdr &msg, const caStatus completionStatus) { caHdr *preply; caStatus opStatus; - if (pDesc) { - errMessage(S_cas_badParameter, - "didnt expect a data descriptor from asynch write"); - } - opStatus = this->allocMsg(0u, &preply); if (opStatus) { return opStatus; @@ -801,7 +803,6 @@ caStatus casStrmClient::hostNameAction() const caHdr *mp = this->ctx.getMsg(); char *pName = (char *) this->ctx.getData(); casChannelI *pciu; - tsDLIter iter(this->chanList); unsigned size; char *pMalloc; @@ -827,7 +828,8 @@ caStatus casStrmClient::hostNameAction() } this->pHostName = pMalloc; - while ( (pciu = iter()) ) { + tsDLFwdIter iter(this->chanList); + while ( (pciu = iter.next()) ) { (*pciu)->setOwner(this->pUserName, this->pHostName); } @@ -845,7 +847,6 @@ caStatus casStrmClient::clientNameAction() const caHdr *mp = this->ctx.getMsg(); char *pName = (char *) this->ctx.getData(); casChannelI *pciu; - tsDLIter iter(this->chanList); unsigned size; char *pMalloc; @@ -866,12 +867,14 @@ caStatus casStrmClient::clientNameAction() pMalloc[size-1]='\0'; this->osiLock(); + if (this->pUserName) { delete [] this->pUserName; } this->pUserName = pMalloc; - while ( (pciu = iter()) ) { + tsDLFwdIter iter(this->chanList); + while ( (pciu = iter.next()) ) { (*pciu)->setOwner(this->pUserName, this->pHostName); } this->osiUnlock(); @@ -1015,16 +1018,16 @@ caStatus casStrmClient::disconnectChan(caResId id) caStatus casStrmClient::eventsOnAction () { casChannelI *pciu; - tsDLIter iter(this->chanList); - this->setEventsOff(); + this->setEventsOn(); // // perhaps this is to slow - perhaps there // should be a queue of modified events // this->osiLock(); - while ( (pciu = iter()) ) { + tsDLFwdIter iter(this->chanList); + while ( (pciu = iter.next()) ) { pciu->postAllModifiedEvents(); } this->osiUnlock(); @@ -1037,7 +1040,7 @@ caStatus casStrmClient::eventsOnAction () // caStatus casStrmClient::eventsOffAction() { - this->setEventsOn(); + this->setEventsOff(); return S_cas_success; } @@ -1271,14 +1274,28 @@ caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) #endif -/* - * casStrmClient::readSyncAction() - */ +// +// casStrmClient::readSyncAction() +// caStatus casStrmClient::readSyncAction() { const caHdr *mp = this->ctx.getMsg(); int status; caHdr *reply; + casChannelI *pChan; + + // + // This messages indicates that the client + // timed out on a read so we must clear out + // any pending asynchronous IO associated with + // a read. + // + this->osiLock(); + tsDLFwdIter iter(this->chanList); + while ( (pChan = iter.next()) ) { + pChan->clearOutstandingReads(); + } + this->osiUnlock(); status = this->allocMsg(0u, &reply); if(status){ @@ -1363,7 +1380,7 @@ caStatus casStrmClient::write() // DBR_STRING is stored outside the DD so it // lumped in with arrays // - if (pHdr->m_count > 1u || pHdr->m_type==DBR_STRING) { + if (pHdr->m_count > 1u) { status = this->writeArrayData(); } else { @@ -1397,7 +1414,14 @@ caStatus casStrmClient::writeScalarData() return S_cas_noMemory; } - gddStat = pDD->genCopy(type, this->ctx.getData()); + if (type==aitEnumFixedString) { + aitFixedString *pFStr = + (aitFixedString *) this->ctx.getData(); + gddStat = pDD->put(*pFStr); + } + else { + gddStat = pDD->genCopy(type, this->ctx.getData()); + } if (gddStat) { pDD->unreference(); return S_cas_badType; @@ -1617,9 +1641,8 @@ const char *casStrmClient::hostName() const // // casStrmClient::createChanResponse() // -caStatus casStrmClient::createChanResponse(casChannelI *, - const caHdr &msg, gdd *pCanonicalName, - const caStatus completionStatus) +caStatus casStrmClient::createChanResponse(const caHdr &msg, + const pvExistReturn &retVal) { casChannel *pChan; casChannelI *pChanI; @@ -1630,11 +1653,15 @@ caStatus casStrmClient::createChanResponse(casChannelI *, this->ctx.getServer()->pvExistTestCompletion(); - if (completionStatus) { - return this->channelCreateFailed(&msg, completionStatus); + if (retVal.getStatus()) { + return this->channelCreateFailed(&msg, retVal.getStatus()); } - if (!pCanonicalName) { + if (!retVal.getString()) { + return this->channelCreateFailed(&msg, S_cas_badParameter); + } + + if (retVal.getString()[0]=='\0') { return this->channelCreateFailed(&msg, S_cas_badParameter); } @@ -1649,9 +1676,7 @@ caStatus casStrmClient::createChanResponse(casChannelI *, // this->osiLock(); - pCanonicalName->markConstant(); - - pPV = this->ctx.getServer()->createPV(*pCanonicalName); + pPV = this->ctx.getServer()->createPV(retVal.getString()); if (!pPV) { this->osiUnlock(); return this->channelCreateFailed(&msg, S_cas_noMemory); @@ -1694,37 +1719,22 @@ caStatus casStrmClient::createChanResponse(casChannelI *, // // caServerI::createPV () // -casPVI *caServerI::createPV (gdd &name) +casPVI *caServerI::createPV (const char *pName) { casPVI *pPVI; - caStatus status; - aitString *pNameStr; // - // dont proceed unless its a valid PV name + // create resource id + // (this does a malloc to obtain space for the string) // - status = casPVI::verifyPVName (name); - if (status) { - return NULL; - } - - // - // this assumes that they did a put() - // and not a putRef() - // - // if this assumption is wrong (and there is no - // way currently to test) it will prove fatal - // to the server - // - name.getRef(pNameStr); - stringId id (pNameStr->string()); + stringId id (pName); this->osiLock (); pPVI = this->stringResTbl.lookup (id); if (!pPVI) { casPV *pPV; - pPV = (*this)->createPV (this->ctx, pNameStr->string()); + pPV = (*this)->createPV (this->ctx, pName); if (pPV) { pPVI = (casPVI *) pPV; } @@ -1772,3 +1782,76 @@ void casStrmClient::removeChannel(casChannelI &chan) this->osiUnlock(); } +// +// casStrmClient::xSend() +// +xSendStatus casStrmClient::xSend(char *pBufIn, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nActualBytes) +{ + xSendStatus stat; + bufSizeT nActualBytesDelta; + + assert (nBytesAvailableToSend>=nBytesNeedToBeSent); + + nActualBytes = 0u; + if (this->blockingState() == xIsntBlocking) { + // + // !! this time fetch may be slowing things down !! + // + stat = this->osdSend(pBufIn, nBytesAvailableToSend, + nActualBytes); + if (stat == xSendOK) { + this->elapsedAtLastSend = osiTime::getCurrent(); + } + return stat; + } + + nActualBytes = 0u; + while (TRUE) { + stat = this->osdSend(&pBufIn[nActualBytes], + nBytesAvailableToSend, nActualBytesDelta); + if (stat != xSendOK) { + return stat; + } + + // + // !! this time fetch may be slowing things down !! + // + this->elapsedAtLastSend = osiTime::getCurrent(); + nActualBytes += nActualBytesDelta; + + if (nBytesNeedToBeSent <= nActualBytesDelta) { + break; + } + nBytesAvailableToSend -= nActualBytesDelta; + nBytesNeedToBeSent -= nActualBytesDelta; + } + return xSendOK; +} + +// +// casStrmClient::xRecv() +// +xRecvStatus casStrmClient::xRecv(char *pBufIn, bufSizeT nBytes, + bufSizeT &nActualBytes) +{ + xRecvStatus stat; + + stat = this->osdRecv(pBufIn, nBytes, nActualBytes); + if (stat==xRecvOK) { + // + // !! this time fetch may be slowing things down !! + // + this->elapsedAtLastRecv = osiTime::getCurrent(); + } + return stat; +} + +// +// casStrmClient::getDebugLevel() +// +unsigned casStrmClient::getDebugLevel() const +{ + return this->getCAS().getDebugLevel(); +} + diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index f3634e8e7..e3154e779 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -30,6 +30,9 @@ * Modification Log: * ----------------- * $Log$ + * Revision 1.6 1996/09/04 20:27:00 jhill + * doccasdef.h + * * Revision 1.5 1996/08/13 22:54:42 jhill * doc * @@ -80,22 +83,18 @@ * 3) some form of locking (similar to (1) above) */ - - #ifndef includecasdefh #define includecasdefh // // EPICS // -#include // EPICS alarm severity/condition -#include // EPICS error codes -#include // EPICS data descriptors +#include "alarm.h" // EPICS alarm severity/condition +#include "errMdef.h" // EPICS error codes +#include "gdd.h" // EPICS data descriptors typedef aitUint32 caStatus; -#include // EPICS event select class -#include // CA server private /* * =========================================================== @@ -106,7 +105,7 @@ typedef aitUint32 caStatus; #define S_cas_success 0 #define S_cas_internal (M_cas| 1) /*Internal failure*/ #define S_cas_noMemory (M_cas| 2) /*Memory allocation failed*/ -#define S_cas_portInUse (M_cas| 3) /*IP port already in use*/ +#define S_cas_bindFail (M_cas| 3) /*Attempt to set server's IP address/port failed*/ #define S_cas_hugeRequest (M_cas | 4) /*Requested op does not fit*/ #define S_cas_sendBlocked (M_cas | 5) /*Blocked for send q space*/ #define S_cas_badElementCount (M_cas | 6) /*Bad element count*/ @@ -132,6 +131,7 @@ typedef aitUint32 caStatus; #define S_cas_badParameter (M_cas | 26) /*bad parameter from server tool*/ #define S_cas_validRequest (M_cas | 27) /*valid request*/ #define S_cas_tooManyEvents (M_cas | 28) /*maximum simult event types exceeded*/ +#define S_cas_noInterface (M_cas | 29) /*server isnt attached to a network*/ /* @@ -152,109 +152,37 @@ typedef aitUint32 caStatus; // -// casAsyncIO - Channel Access Asynchronous IO API Class +// pvExistReturn +// Only for use with caServer::pvExistTest() // -// The following virtual functions allow for asynchronous completion: -// caServer::pvExistTest() -// casPV::read() -// casPV::write() -// To initiate asynchronous completion create a casAsyncIO object -// inside one of the above virtual functions and return the status code -// S_casApp_asyncCompletion -// -// All asynchronous completion data must be returned in the -// gdd provided in the virtual functions parameters. -// -// Deletion Responsibility -// -------- -------------- -// o the server lib will not call "delete" directly for any -// casAsyncIO created by the server tool because we dont know -// that "new" was called to create the object. -// o The server tool is responsible for reclaiming storage for any -// casAsyncIO it creates. The destroy virtual function will -// assist the server tool with this responsibility. The -// virtual function casAsyncIO::destroy() does a "delete this". -// o Avoid deleting the casAsyncIO immediately after calling -// postIOCompletion(). Instead proper operation requires that -// the server tool wait for the server lib to call destroy after -// the response is succesfully queued to the client -// o If for any reason the server tool needs to cancel an IO -// operation then it should post io completion with status -// S_casApp_canceledAsyncIO. Deleting the asyncronous io -// object prior to its being allowed to forward an IO termination -// message to the client will result in NO IO CALL BACK TO THE -// CLIENT PROGRAM (in this situation a warning message will be printed by -// the server lib). -// -class casAsyncIO : private casAsyncIOI { +class pvExistReturn { public: // - // casAsyncIO() + // for use by the server tool when creating a return value // - // Any DD ptr supplied here is used if postIOCompletion() - // is called with a nill DD pointer + inline pvExistReturn(caStatus status=S_casApp_pvNotFound, + const char* pCanonicalNameStr=0); + inline pvExistReturn(caStatus status, char* pCanonicalNameStr); // - casAsyncIO(const casCtx &ctx, gdd *pValue=0) : - casAsyncIOI(ctx, *this, pValue) {} - + // for use by the server lib when extracting the result // - // force virtual destructor + inline const caStatus getStatus() const; + inline const char *getString() const; // - virtual ~casAsyncIO() {} - + // these make certain that copy and assignment are correct // - // called by the server lib after the response message - // is succesfully queued to the client or when the - // IO operation is canceled (client disconnects etc). - // - // default destroy executes a "delete this". - // - virtual void destroy(); - - // - // place notification of IO completion on the event queue - // (this function does not delete the casAsyncIO object). - // Only the first call to this function has any effect. - // - caStatus postIOCompletion(caStatus completionStatusIn, gdd *pValue=0) - { - return this->casAsyncIOI::postIOCompletion(completionStatusIn, pValue); - } - - // - // Find the server associated with this async IO - // ****WARNING**** - // this returns NULL if the async io isnt currently installed - // into a server - // *************** - // - caServer *getCAS() - { - return this->casAsyncIOI::getCAS(); - } - - // - // return gdd DD ptr stored in base - // (a mechanism to avoid duplicate storage of DD ptr - // - in the base and in the derived) - // - gdd *getValuePtr () - { - return this->casAsyncIOI::getValuePtr(); - } - - // - // release any data optionally attached to the asynchronous IO - // object by the constructor - used when the asynchronous - // io saves data but does not return datai with the post - // (ie write) - // - void clrValue() - { - this->casAsyncIOI::clrValue(); - } + inline pvExistReturn(pvExistReturn &init); + inline pvExistReturn(const pvExistReturn &init); + inline pvExistReturn& operator=(pvExistReturn &rhs); + inline pvExistReturn& operator=(const pvExistReturn &rhs); +private: + caStatus stat; + aitString str; }; +#include "casEventMask.h" // EPICS event select class +#include "casInternal.h" // CA server private + class caServerI; // @@ -290,22 +218,36 @@ public: virtual void show (unsigned level); // + // pvExistTest() + // // The server tool is encouraged to accept multiple PV name - // aliases for the same PV here. However, a unique canonical name - // must be selected for each PV. + // aliases for the same PV here. However, one unique canonical name + // must be selected by the srever tool and returned to the + // server lib for each PV. The server will use this canonical + // name to prevent internal duplication of data structures for + // process variables that have multiple aliases. // - // returns S_casApp_success and fills in canonicalPVName - // if the PV is in this server tool + // o returns S_casApp_success and a valid canonical name string + // when the PV is in this server tool // - // returns S_casApp_pvNotFound if the PV does not exist in + // o returns S_casApp_pvNotFound if the PV does not exist in // the server tool - // - // The server tool returns the unique canonical name for - // the pv into the gdd. A gdd is used here becuase this - // operation is allowed to complete asynchronously. // - virtual caStatus pvExistTest (const casCtx &ctx, const char *pPVName, - gdd &canonicalPVName) = 0; + // Examples: + // caServerXXX::pvExistTest(const casCtx &ctx, const char *pPVName) + // { + // return pvExistReturn(S_casApp_success, pPVName); // common + // return pvExistReturn(S_casApp_pvNotFound); // no PV by that name + // + // const char *pConstName = "myPVName"; + // char pName[9] = "myPVName"; + // return pvExistReturn(S_casApp_success, pConstName); // efficent + // return pvExistReturn(S_casApp_success, pName"); // less efficent + // return pvExistReturn(S_casApp_asyncCompletion); // not now + // } + // + virtual pvExistReturn pvExistTest (const casCtx &ctx, + const char *pPVName)=0; // // createPV() is called each time that a PV is attached to @@ -543,5 +485,214 @@ public: casPV *getPV(); }; +// +// Asynchronous IO Classes +// +// The following virtual functions allow for asynchronous completion: +// +// Vitrtual Function Asynchronous IO Class +// ----------------- --------------------- +// caServer::pvExistTest() casAsyncPVExistIO +// casPV::read() casAsyncReadIO +// casPV::write() casAsyncWriteIO +// +// To initiate asynchronous completion create a corresponding +// asynchronous IO object from the table above from within +// one of the above virtual functions and return the status code +// S_casApp_asyncCompletion. Use the member function +// "postIOCompletion()" to inform the server library that the +// requested operation has completed. +// +// +// Deletion Responsibility +// -------- -------------- +// o the server lib will not call "delete" directly for any +// casAsyncIO created by the server tool because we dont know +// that "new" was called to create the object. +// o The server tool is responsible for reclaiming storage for any +// casAsyncIO it creates. The destroy virtual function will +// assist the server tool with this responsibility. The +// virtual function casAsyncIO::destroy() does a "delete this". +// o Avoid deleting the casAsyncIO immediately after calling +// postIOCompletion(). Instead proper operation requires that +// the server tool wait for the server lib to call destroy after +// the response is succesfully queued to the client +// o If for any reason the server tool needs to cancel an IO +// operation then it should post io completion with status +// S_casApp_canceledAsyncIO. Deleting the asyncronous io +// object prior to its being allowed to forward an IO termination +// message to the client will result in NO IO CALL BACK TO THE +// CLIENT PROGRAM (in this situation a warning message will be printed by +// the server lib). +// + +// +// casAsyncIO +// +// this class implements a common virtual destroy for +// all of the asynchronous IO classes +// +class casAsyncIO { +public: + // + // force virtual destructor + // + virtual ~casAsyncIO(); + + // + // called by the server lib after the response message + // is succesfully queued to the client or when the + // IO operation is canceled (client disconnects etc). + // + // default destroy executes a "delete this". + // + virtual void destroy(); +}; + +// +// casAsyncReadIO +// - for use with casPV::read() +// +// **Warning** +// The server tool must reference the gdd object +// passed in the arguments to casPV::read() if it is +// necessary for this gdd object to continue to exist +// after the return from casPV::read(). If this +// is done then it is suggested that this gdd object +// be referenced in the constructor, and unreferenced +// in the destructor, for the class deriving from +// casAsyncReadIO. +// ** +class casAsyncReadIO : public casAsyncIO, private casAsyncRdIOI { +public: + // + // casAsyncReadIO() + // + casAsyncReadIO(const casCtx &ctx) : + casAsyncRdIOI(ctx, *this) {} + + // + // force virtual destructor + // + virtual ~casAsyncReadIO(); + + // + // place notification of IO completion on the event queue + // (this function does not delete the casAsyncIO object). + // Only the first call to this function has any effect. + // + caStatus postIOCompletion(caStatus completionStatusIn, gdd &valueRead) + { + return this->casAsyncRdIOI::postIOCompletion ( + completionStatusIn, valueRead); + } + + // + // Find the server associated with this async IO + // ****WARNING**** + // this returns NULL if the async io isnt currently installed + // into a server + // *************** + // + caServer *getCAS() + { + return this->casAsyncRdIOI::getCAS(); + } +}; + +// +// casAsyncWriteIO +// - for use with casPV::write() +// +// **Warning** +// The server tool must reference the gdd object +// passed in the arguments to casPV::write() if it is +// necessary for this gdd object to continue to exist +// after the return from casPV::write(). If this +// is done then it is suggested that this gdd object +// be referenced in the constructor, and unreferenced +// in the destructor, for the class deriving from +// casAsyncWriteIO. +// ** +// +class casAsyncWriteIO : public casAsyncIO, private casAsyncWtIOI { +public: + // + // casAsyncWriteIO() + // + casAsyncWriteIO(const casCtx &ctx) : + casAsyncWtIOI(ctx, *this) {} + + // + // force virtual destructor + // + virtual ~casAsyncWriteIO(); + + // + // place notification of IO completion on the event queue + // (this function does not delete the casAsyncIO object). + // Only the first call to this function has any effect. + // + caStatus postIOCompletion(caStatus completionStatusIn) + { + return this->casAsyncWtIOI::postIOCompletion (completionStatusIn); + } + + // + // Find the server associated with this async IO + // ****WARNING**** + // this returns NULL if the async io isnt currently installed + // into a server + // *************** + // + caServer *getCAS() + { + return this->casAsyncWtIOI::getCAS(); + } +}; + +// +// casAsyncPVExistIO +// - for use with caServer::pvExistTest() +// +class casAsyncPVExistIO : public casAsyncIO, private casAsyncExIOI { +public: + // + // casAsyncPVExistIO() + // + // Any DD ptr supplied here is used if postIOCompletion() + // is called with a nill DD pointer + // + casAsyncPVExistIO(const casCtx &ctx) : + casAsyncExIOI(ctx, *this) {} + + // + // force virtual destructor + // + virtual ~casAsyncPVExistIO(); + + // + // place notification of IO completion on the event queue + // (this function does not delete the casAsyncIO object). + // Only the first call to this function has any effect. + // + caStatus postIOCompletion(const pvExistReturn &retValIn) + { + return this->casAsyncExIOI::postIOCompletion (retValIn); + } + + // + // Find the server associated with this async IO + // ****WARNING**** + // this returns NULL if the async io isnt currently installed + // into a server + // *************** + // + caServer *getCAS() + { + return this->casAsyncExIOI::getCAS(); + } +}; + #endif // ifdef includecasdefh (this must be the last line in this file) diff --git a/src/cas/generic/inBuf.cc b/src/cas/generic/inBuf.cc index ef0214768..f68b1e588 100644 --- a/src/cas/generic/inBuf.cc +++ b/src/cas/generic/inBuf.cc @@ -29,42 +29,18 @@ * * History * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:15 jhill + * ca server installation + * * */ -#include - -// -// inBuf::inBuf() -// -inBuf::inBuf(casMsgIO &virtualCircuit, osiMutex &mutexIn) : - mutex(mutexIn), - io(virtualCircuit) -{ - assert(&this->io); - - this->bytesInBuffer = 0u; - this->nextReadIndex = 0u; - this->bufSize = 0u; - this->pBuf = NULL; -} - -// -// inBuf::init() -// -caStatus inBuf::init() -{ - this->bufSize = io.optimumBufferSize(); - this->pBuf = new char [this->bufSize]; - if (!this->pBuf) { - this->bufSize = 0u; - return S_cas_noMemory; - } - return S_cas_success; -} +#include "server.h" +#include "inBufIL.h" // inBuf in line func // // inBuf::~inBuf() +// (virtual destructor) // inBuf::~inBuf() { @@ -73,7 +49,10 @@ inBuf::~inBuf() } } -void inBuf::show(unsigned level) +// +// inBuf::show() +// +void inBuf::show(unsigned level) const { if (level>1u) { printf( @@ -82,13 +61,18 @@ void inBuf::show(unsigned level) } } +// +// inBuf::fill() +// casFillCondition inBuf::fill() { unsigned bytesReq; unsigned bytesRecv; xRecvStatus stat; - assert(this->pBuf); + if (!this->pBuf) { + return casFillDisconnect; + } // // move back any prexisting data to the start of the buffer @@ -115,7 +99,7 @@ casFillCondition inBuf::fill() return casFillFull; } - stat = this->io.xRecv( &this->pBuf[this->bytesInBuffer], + stat = this->xRecv(&this->pBuf[this->bytesInBuffer], bytesReq, bytesRecv); if (stat != xRecvOK) { return casFillDisconnect; @@ -125,6 +109,16 @@ casFillCondition inBuf::fill() } assert (bytesRecv<=bytesReq); this->bytesInBuffer += bytesRecv; + + if (this->getDebugLevel()>2u) { + char buf[64]; + + this->clientHostName(buf, sizeof(buf)); + + printf ("CAS: incomming %u byte msg from %s\n", + bytesRecv, buf); + } + if (this->bufSize==this->bytesInBuffer) { return casFillFull; } diff --git a/src/cas/generic/outBuf.cc b/src/cas/generic/outBuf.cc index 21ca8a128..449d75ce8 100644 --- a/src/cas/generic/outBuf.cc +++ b/src/cas/generic/outBuf.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.4 1996/09/16 18:24:07 jhill + * vxWorks port changes + * * Revision 1.3 1996/09/04 20:27:01 jhill * doccasdef.h * @@ -41,21 +44,18 @@ * */ - - -#include +#include "server.h" +#include "outBufIL.h" // outBuf in line func // // outBuf::outBuf() // -outBuf::outBuf(casMsgIO &virtualCircuit, osiMutex &mutexIn) : - io(virtualCircuit), +outBuf::outBuf(osiMutex &mutexIn, unsigned bufSizeIn) : mutex(mutexIn), pBuf(NULL), - bufSize(io.optimumBufferSize()), + bufSize(bufSizeIn), stack(0u) { - assert(&io); } // @@ -67,6 +67,7 @@ caStatus outBuf::init() if (!this->pBuf) { return S_cas_noMemory; } + memset (this->pBuf, '\0', this->bufSize); return S_cas_success; } @@ -162,13 +163,14 @@ void outBuf::commitMsg () if (this->getDebugLevel()) { ca_printf ( - "CAS Response => cmd=%d id=%x typ=%d cnt=%d psz=%d avail=%x\n", +"CAS Response => cmd=%d id=%x typ=%d cnt=%d psz=%d avail=%x outBuf ptr=%lx\n", mp->m_cmmd, mp->m_cid, mp->m_type, mp->m_count, mp->m_postsize, - mp->m_available); + mp->m_available, + (long)mp); } /* @@ -191,8 +193,7 @@ void outBuf::commitMsg () // // outBuf::flush() // -casFlushCondition outBuf::flush(casFlushRequest req, - bufSizeT spaceRequired) +casFlushCondition outBuf::flush(casFlushRequest req, bufSizeT spaceRequired) { bufSizeT nBytes; bufSizeT stackNeeded; @@ -219,41 +220,55 @@ casFlushCondition outBuf::flush(casFlushRequest req, } } - stat = this->io.xSend(this->pBuf, this->stack, - nBytesNeeded, nBytes); - if (nBytes) { - bufSizeT len; + if (nBytesNeeded==0u) { + this->mutex.osiUnlock(); + return casFlushCompleted; + } - if (nBytes >= this->stack) { - this->stack=0u; - cond = casFlushCompleted; + nBytes = 0u; + stat = this->xSend(this->pBuf, this->stack, + nBytesNeeded, nBytes); + if (stat == xSendOK) { + if (nBytes) { + bufSizeT len; + char buf[64]; + + if (nBytes >= this->stack) { + this->stack=0u; + cond = casFlushCompleted; + } + else { + len = this->stack-nBytes; + // + // memmove() is ok with overlapping buffers + // + memmove (this->pBuf, &this->pBuf[nBytes], len); + this->stack = len; + cond = casFlushPartial; + } + + if (this->getDebugLevel()>2u) { + this->clientHostName(buf,sizeof(buf)); + ca_printf( + "CAS: Sent a %d byte reply to %s\n", + nBytes, buf); + } } else { - len = this->stack-nBytes; - // - // memmove() is ok with overlapping buffers - // - memmove (this->pBuf, &this->pBuf[nBytes], len); - this->stack = len; - cond = casFlushPartial; + cond = casFlushNone; } } else { - cond = casFlushNone; - } - - if (stat!=xSendOK) { cond = casFlushDisconnect; } this->mutex.osiUnlock(); return cond; - } // // outBuf::show(unsigned level) // -void outBuf::show(unsigned level) +void outBuf::show(unsigned level) const { if (level>1u) { printf( @@ -262,3 +277,11 @@ void outBuf::show(unsigned level) } } +// +// outBuf::sendBlockSignal() +// +void outBuf::sendBlockSignal() +{ + fprintf(stderr, "In virtula base sendBlockSignal() ?\n"); +} + diff --git a/src/cas/generic/server.h b/src/cas/generic/server.h index 6af5119e4..28bb8189e 100644 --- a/src/cas/generic/server.h +++ b/src/cas/generic/server.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.11 1996/09/16 18:24:09 jhill + * vxWorks port changes + * * Revision 1.10 1996/09/04 20:27:02 jhill * doccasdef.h * @@ -87,19 +90,21 @@ HDRVERSIONID(serverh, "%W% %G%") // EPICS // #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -#include +#include "epicsAssert.h" // // CA // -#include -#include -#include -#include +#include "caCommonDef.h" +#include "caerr.h" +#include "casdef.h" +#include "osiTime.h" // // CAS // +#include "casAddr.h" +#include "osiMutexCAS.h" // NOOP on single threaded OS void casVerifyFunc(const char *pFile, unsigned line, const char *pExp); void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment); #define serverToolDebug(COMMENT) \ @@ -108,87 +113,25 @@ void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment) caStatus createDBRDD(unsigned dbrType, aitIndex dbrCount, gdd *&pDescRet); caStatus copyBetweenDD(gdd &dest, gdd &src); -// -// casMsgIO -// enum xRecvStatus {xRecvOK, xRecvDisconnect}; enum xSendStatus {xSendOK, xSendDisconnect}; enum xBlockingStatus {xIsBlocking, xIsntBlocking}; enum casIOState {casOnLine, casOffLine}; typedef unsigned bufSizeT; -class casMsgIO { -public: - casMsgIO(); - virtual ~casMsgIO(); - - osiTime timeOfLastXmit() const; - osiTime timeOfLAstRecv() const; - - // - // show status of IO subsystem - // (cant be const because a lock is taken) - // - void show (unsigned level); - - // - // device dependent recv - // - xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); - xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv); - - virtual caStatus init()=0; - virtual bufSizeT optimumBufferSize ()=0; - virtual bufSizeT incommingBytesPresent() const; - virtual casIOState state() const=0; - virtual void hostNameFromAddr (char *pBuf, unsigned bufSize)=0; - virtual int getFileDescriptor() const; - void setNonBlocking() - { - this->xSetNonBlocking(); - this->blockingStatus = xIsntBlocking; - } - - // - // only for use with DG io - // - virtual void sendBeacon(char &msg, bufSizeT length, - aitUint32 &m_avail); - -private: - // - // private data members - // - osiTime elapsedAtLastSend; - osiTime elapsedAtLastRecv; - xBlockingStatus blockingStatus; - - virtual xSendStatus osdSend (const char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual) =0; - virtual xRecvStatus osdRecv (char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual) =0; - virtual void osdShow (unsigned level) const = 0; - virtual void xSetNonBlocking(); -}; - -#include // OS dependent -#include // IO dependent enum casProcCond {casProcOk, casProcDisconnect}; - /* * maximum peak log entries for each event block (registartion) * (events cached into the last queue entry if over flow occurs) */ -const unsigned char individualEventEntries = 16u; +#define individualEventEntries 16u /* * maximum average log entries for each event block (registartion) * (events cached into the last queue entry if over flow occurs) */ -const unsigned char averageEventEntries = 4u; +#define averageEventEntries 4u typedef caResId caEventId; @@ -203,59 +146,36 @@ class caServerI; // class casEventSys { public: - casEventSys (casCoreClient &coreClientIn) : - coreClient(coreClientIn), - numEventBlocks(0u), - maxLogEntries(individualEventEntries), - eventsOff(aitFalse) - { - } - init() - { - if (mutex.init()) { - return S_cas_noMemory; - } - return S_cas_success; - } + inline casEventSys (casCoreClient &coreClientIn); + + inline caStatus init(); + ~casEventSys(); - void show(unsigned level); + void show(unsigned level) const; casProcCond process(); - //void cancelIODone (casAsyncIO *pEventToDelete); - void installMonitor(); void removeMonitor(); - void removeFromEventQueue(casEvent &); + inline void removeFromEventQueue(casEvent &); inline void addToEventQueue(casEvent &); - void insertEventQueue(casEvent &insert, casEvent &prevEvent); - void pushOnToEventQueue(casEvent &event); + inline void insertEventQueue(casEvent &insert, casEvent &prevEvent); + inline void pushOnToEventQueue(casEvent &event); - aitBool full(); + inline aitBool full(); inline casMonitor *resIdToMon(const caResId id); - casCoreClient &getCoreClient() - { - return this->coreClient; - } + inline casCoreClient &getCoreClient(); - aitBool getEventsOff () const - { - return this->eventsOff?aitTrue:aitFalse; - } + inline aitBool getEventsOff () const; - void setEventsOn() - { - this->eventsOff = aitFalse; - } + inline void setEventsOn(); + + inline void setEventsOff(); - void setEventsOff() - { - this->eventsOff = aitTrue; - } private: tsDLList eventLogQue; osiMutex mutex; @@ -265,49 +185,6 @@ private: unsigned char eventsOff; }; -// -// casEventSys::insertEventQueue() -// -inline void casEventSys::insertEventQueue(casEvent &insert, casEvent &prevEvent) -{ - this->mutex.osiLock(); - this->eventLogQue.insertAfter(insert, prevEvent); - this->mutex.osiUnlock(); -} - -// -// casEventSys::pushOnToEventQueue() -// -inline void casEventSys::pushOnToEventQueue(casEvent &event) -{ - this->mutex.osiLock(); - this->eventLogQue.push(event); - this->mutex.osiUnlock(); -} - -// -// casEventSys::removeFromEventQueue() -// -inline void casEventSys::removeFromEventQueue(casEvent &event) -{ - this->mutex.osiLock(); - this->eventLogQue.remove(event); - this->mutex.osiUnlock(); -} - -// -// casEventSys::full() -// -inline aitBool casEventSys::full() -{ - if (this->eventLogQue.count()>=this->maxLogEntries) { - return aitTrue; - } - else { - return aitFalse; - } -} - // // casClientMon // @@ -334,64 +211,35 @@ private: class casCtx { public: - casCtx() : - pData(NULL), pCAS(NULL), pClient(NULL), - pChannel(NULL), pPV(NULL) - { - memset(&this->msg, 0, sizeof(this->msg)); - } + inline casCtx(); // // get // - const caHdr *getMsg() const {return (const caHdr *) &this->msg;}; - void *getData() const {return this->pData;}; - caServerI * getServer() const {return this->pCAS;} - casCoreClient * getClient() const {return this->pClient;} - casPVI * getPV() const {return this->pPV;} - casChannelI * getChannel() const {return this->pChannel;} + inline const caHdr *getMsg() const; + inline void *getData() const; + inline caServerI * getServer() const; + inline casCoreClient * getClient() const; + inline casPVI * getPV() const; + inline casChannelI * getChannel() const; // // set // (assumes incoming message is in network byte order) // - void setMsg(const char *pBuf) - { - // - // copy as raw bytes in order to avoid - // alignment problems - // - memcpy (&this->msg, pBuf, sizeof(this->msg)); - this->msg.m_cmmd = ntohs (this->msg.m_cmmd); - this->msg.m_postsize = ntohs (this->msg.m_postsize); - this->msg.m_type = ntohs (this->msg.m_type); - this->msg.m_count = ntohs (this->msg.m_count); - this->msg.m_cid = ntohl (this->msg.m_cid); - this->msg.m_available = ntohl (this->msg.m_available); - }; - void setData(void *p) {this->pData = p;}; - void setServer(caServerI *p) - { - this->pCAS = p; - } - void setClient(casCoreClient *p) { - this->pClient = p; - } - void setPV(casPVI *p) {this->pPV = p;} - void setChannel(casChannelI *p) {this->pChannel = p;} + inline void setMsg(const char *pBuf); - void show (unsigned level) - { - printf ("casCtx at %x\n", (unsigned) this); - if (level >= 1u) { - printf ("\tpMsg = %x\n", (unsigned) &this->msg); - printf ("\tpData = %x\n", (unsigned) pData); - printf ("\tpCAS = %x\n", (unsigned) pCAS); - printf ("\tpClient = %x\n", (unsigned) pClient); - printf ("\tpChannel = %x\n", (unsigned) pChannel); - printf ("\tpPV = %x\n", (unsigned) pPV); - } - } + inline void setData(void *p); + + inline void setServer(caServerI *p); + + inline void setClient(casCoreClient *p); + + inline void setPV(casPVI *p); + + inline void setChannel(casChannelI *p); + + void show (unsigned level) const; private: caHdr msg; // ca message header void *pData; // pointer to data following header @@ -411,71 +259,72 @@ enum casFillCondition{ // class inBuf { public: - inBuf(casMsgIO &, osiMutex &); - caStatus init(); //constructor does not return status + inline inBuf (osiMutex &, unsigned bufSizeIn); + inline caStatus init(); //constructor does not return status virtual ~inBuf(); - bufSizeT bytesPresent() const { - return this->bytesInBuffer-this->nextReadIndex; - } + inline bufSizeT bytesPresent() const; - bufSizeT bytesAvailable() const { - bufSizeT bp; - bufSizeT ibp; - bp = this->bytesPresent(); - ibp = this->io.incommingBytesPresent(); - return bp + ibp; - } + inline bufSizeT bytesAvailable() const ; - aitBool full() const - { - if (this->bytesPresent()>=this->bufSize) { - return aitTrue; - } - return aitFalse; - } + inline aitBool full() const; - void clear() - { - this->bytesInBuffer = 0u; - this->nextReadIndex = 0u; - } + inline void clear(); - // - // - // - char *msgPtr() const {return &this->pBuf[this->nextReadIndex];} + inline char *msgPtr() const; - // - // - // - void removeMsg(unsigned nBytes) { - this->nextReadIndex += nBytes; - assert(this->nextReadIndex<=this->bytesInBuffer); - } + inline void removeMsg(unsigned nBytes); // // fill the input buffer with any incoming messages // - casFillCondition fill(); + casFillCondition fill (); - void show(unsigned level); + void show (unsigned level) const; + + virtual unsigned getDebugLevel() const = 0; + virtual bufSizeT incommingBytesPresent() const = 0; + virtual xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv) = 0; + virtual void clientHostName (char *pBuf, + unsigned bufSize) const = 0; - virtual unsigned getDebugLevel()=0; private: osiMutex &mutex; - casMsgIO &io; char *pBuf; bufSizeT bufSize; bufSizeT bytesInBuffer; bufSizeT nextReadIndex; }; +// +// dgInBuf +// +class dgInBuf : public inBuf { +public: + inline dgInBuf (osiMutex &mutexIn, unsigned bufSizeIn); + virtual ~dgInBuf(); + + inline void clear(); + + inline int hasAddress() const; + + inline const caAddr getSender() const; + + xRecvStatus xRecv (char *pBufIn, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv); + + virtual xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv, caAddr &sender) = 0; +private: + casOpaqueAddr from; +}; + // // outBuf // enum casFlushCondition{ - casFlushNone, + casFlushNone, casFlushPartial, casFlushCompleted, casFlushDisconnect}; @@ -485,32 +334,20 @@ enum casFlushRequest{ class outBuf { public: - outBuf (casMsgIO &, osiMutex &); + outBuf (osiMutex &, unsigned bufSizeIn); caStatus init(); //constructor does not return status - virtual ~outBuf(); + virtual ~outBuf()=0; - // - // number of bytes in the output queue? - // - bufSizeT bytesPresent() const - { - return this->stack; - } + inline bufSizeT bytesPresent() const; - // - // number of bytes unused in the output queue? - // - bufSizeT bytesFree() const - { - return this->bufSize - this->stack; - } + inline bufSizeT bytesFree() const; // // flush output queue // (returns the number of bytes sent) // casFlushCondition flush(casFlushRequest req = casFlushAll, - bufSizeT spaceRequired=0u); + bufSizeT spaceRequired=0u); // // allocate message buffer space @@ -523,31 +360,50 @@ public: // void commitMsg (); - // - // release an allocated message (but dont send it) - // - void discardMsg () - { - this->mutex.osiUnlock(); - }; + void show(unsigned level) const; - void show(unsigned level); + virtual unsigned getDebugLevel() const = 0; + virtual void sendBlockSignal(); - virtual unsigned getDebugLevel()=0; - virtual void sendBlockSignal()=0; + // + // io dependent + // + virtual xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent) = 0; + virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0; - void clear() - { - this->stack = 0u; - } + inline void clear(); + private: - casMsgIO &io; osiMutex &mutex; char *pBuf; const bufSizeT bufSize; bufSizeT stack; }; +// +// dgOutBuf +// +class dgOutBuf : public outBuf { +public: + inline dgOutBuf (osiMutex &mutexIn, unsigned bufSizeIn); + + virtual ~dgOutBuf(); + + inline caAddr getRecipient(); + + inline void setRecipient(const caAddr &addr); + + inline void clear(); + + xSendStatus xSend (char *pBufIn, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); + + virtual xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent, + bufSizeT &nBytesSent, const caAddr &recipient) = 0; +private: + casOpaqueAddr to; +}; // @@ -555,84 +411,66 @@ private: // (this will eventually support direct communication // between the client lib and the server lib) // -class casCoreClient; - -typedef caStatus (casCoreClient::*pAsyncIoCallBack) - (casChannelI *pChan, const caHdr &, gdd *, const caStatus); - class casCoreClient : public osiMutex, public ioBlocked, public casEventSys { public: casCoreClient(caServerI &serverInternal); - caStatus init() - { - if (this->osiMutex::init()) { - return S_cas_noMemory; - } - return this->casEventSys::init(); - } + caStatus init(); + virtual ~casCoreClient(); virtual void destroy(); virtual caStatus disconnectChan(caResId id); virtual void eventSignal() = 0; virtual void eventFlush() = 0; virtual caStatus start () = 0; - virtual void show (unsigned level); + virtual void show (unsigned level) const; virtual void installChannel (casChannelI &); virtual void removeChannel (casChannelI &); - void installAsyncIO(casAsyncIOI &ioIn) - { - this->osiLock(); - this->ioInProgList.add(ioIn); - this->osiUnlock(); - } + inline void installAsyncIO(casAsyncIOI &ioIn); - void removeAsyncIO(casAsyncIOI &ioIn) - { - this->osiLock(); - this->ioInProgList.remove(ioIn); - this->osiUnlock(); - } + inline void removeAsyncIO(casAsyncIOI &ioIn); - casRes *lookupRes(const caResId &idIn, casResType type); + inline casRes *lookupRes(const caResId &idIn, casResType type); - caServerI &getCAS() const {return *this->ctx.getServer();} - - caStatus asyncIOCompletion(casChannelI *pChan, const caHdr &msg, - gdd *pDesc, caStatus completionStatus); + inline caServerI &getCAS() const; virtual caStatus monitorResponse(casChannelI *, const caHdr &, gdd *, const caStatus); + // + // one virtual function for each CA request type that has + // asynchronous completion + // + virtual caStatus asyncSearchResponse(casDGIntfIO &outMsgIO, + const caAddr &outAddr, const caHdr &, const pvExistReturn &); + virtual caStatus createChanResponse(const caHdr &, + const pvExistReturn &); + virtual caStatus readResponse(casChannelI *, const caHdr &, + gdd *, const caStatus); + virtual caStatus readNotifyResponse(casChannelI *, const caHdr &, + gdd *, const caStatus); + virtual caStatus writeResponse(casChannelI *, const caHdr &, + const caStatus); + virtual caStatus writeNotifyResponse(casChannelI *, const caHdr &, + const caStatus); + + // + // The following are only used with async IO for + // DG clients + // + virtual caAddr fetchRespAddr(); + virtual casDGIntfIO* fetchOutIntf(); protected: casCtx ctx; private: tsDLList ioInProgList; - // - // one virtual function for each CA request type that has - // asynchronous completion - // - virtual caStatus searchResponse(casChannelI *, const caHdr &, - gdd *, const caStatus); - virtual caStatus createChanResponse(casChannelI *, - const caHdr &, gdd *, const caStatus); - virtual caStatus readResponse(casChannelI *, const caHdr &, - gdd *, const caStatus); - virtual caStatus readNotifyResponse(casChannelI *, - const caHdr &, gdd *, const caStatus); - virtual caStatus writeResponse(casChannelI *, const caHdr &, - gdd *, const caStatus); - virtual caStatus writeNotifyResponse(casChannelI *, - const caHdr &, gdd *, const caStatus); - // // static members // static void loadProtoJumpTable(); - static pAsyncIoCallBack asyncIOJumpTable[CA_PROTO_LAST_CMMD+1u]; static int msgHandlersInit; }; @@ -641,13 +479,13 @@ private: // class casClient; typedef caStatus (casClient::*pCASMsgHandler) (); -class casClient : public inBuf, public outBuf, public casCoreClient { +class casClient : public casCoreClient { public: - casClient (caServerI &, casMsgIO &); + casClient (caServerI &, inBuf &, outBuf &); caStatus init(); //constructor does not return status virtual ~casClient (); - void show(unsigned level); + void show(unsigned level) const; // // send error response to a message @@ -663,23 +501,13 @@ public: // inline casChannelI *resIdToChannel(const caResId &id); - inline unsigned getDebugLevel(); + virtual void clientHostName (char *pBuf, + unsigned bufSize) const = 0; - int getFD() const - { - return this->msgIO.getFileDescriptor(); - } - void setNonBlocking() - { - this->msgIO.setNonBlocking(); - } - void sendBeacon(char &msg, bufSizeT length, - aitUint32 &m_avail) - { - this->msgIO.sendBeacon(msg, length, m_avail); - } protected: unsigned minor_version_number; + osiTime elapsedAtLastSend; + osiTime elapsedAtLastRecv; caStatus processMsg(); @@ -699,8 +527,9 @@ protected: const void *dp, const char *pFileName, const unsigned lineno); - casMsgIO &msgIO; private: + inBuf &inBufRef; + outBuf &outBufRef; // // dump message to stderr @@ -748,13 +577,14 @@ private: // // casStrmClient // -class casStrmClient : public casClient, public tsDLNode { +class casStrmClient : public inBuf, public outBuf, public casClient, + public tsDLNode { public: - casStrmClient (caServerI &, casMsgIO &); + casStrmClient (caServerI &cas); caStatus init(); //constructor does not return status ~casStrmClient(); - void show(unsigned level); + void show (unsigned level) const; // // installChannel() @@ -770,16 +600,15 @@ public: // one function for each CA request type that has // asynchronous completion // - caStatus createChanResponse(casChannelI *pChan, const caHdr &msg, - gdd *pDesc, const caStatus status); + virtual caStatus createChanResponse(const caHdr &, const pvExistReturn &); caStatus readResponse(casChannelI *pChan, const caHdr &msg, gdd *pDesc, const caStatus status); caStatus readNotifyResponse(casChannelI *pChan, const caHdr &msg, gdd *pDesc, const caStatus status); caStatus writeResponse(casChannelI *pChan, const caHdr &msg, - gdd *pDesc, const caStatus status); + const caStatus status); caStatus writeNotifyResponse(casChannelI *pChan, const caHdr &msg, - gdd *pDesc, const caStatus status); + const caStatus status); caStatus monitorResponse(casChannelI *pChan, const caHdr &msg, gdd *pDesc, const caStatus status); @@ -795,11 +624,12 @@ public: const char *userName () const; caStatus disconnectChan (caResId id); + + unsigned getDebugLevel() const; private: tsDLList chanList; char *pUserName; char *pHostName; - struct cas_io_in_prog *ioBlockCache; // // createChannel() @@ -847,66 +677,57 @@ private: caStatus writeArrayData(); caStatus writeScalarData(); caStatus writeString(); + + // + // io independent send/recv + // + xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); + xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv); + virtual xBlockingStatus blockingState() const = 0; + virtual xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual) = 0; + virtual xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual) = 0; }; +class casDGIntfIO; + // // casDGClient // -class casDGClient : private casDGIO, private casClient { +class casDGClient : public dgInBuf, public dgOutBuf, public casClient { public: casDGClient (caServerI &serverIn); - caStatus init() //constructor does not return status - { - caStatus status; + caStatus init(); //constructor does not return status - // - // init the base classes - // - status = casDGIO::init(); - if (status) { - return status; - } - status = this->casClient::init(); - if (status) { - return status; - } - return this->start(); - } - - void show(unsigned level); + void show (unsigned level) const; // // only for use with DG io // - void sendDGBeacon(char &msg, bufSizeT length, - aitUint32 &m_avail) - { - this->casClient::sendBeacon(msg, length, m_avail); - } + static void sendBeacon(casDGIntfIO &io); void destroy(); - int getFD() const - { - return this->casClient::getFD(); - } + void processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO); + + unsigned getDebugLevel() const; protected: - void process(); casProcCond eventSysProcess() { return this->casEventSys::process(); } - casFlushCondition flush(casFlushRequest req = casFlushAll, - bufSizeT spaceRequired=0u) - { - return this->outBuf::flush(req,spaceRequired); - } private: + casDGIntfIO *pOutMsgIO; + casDGIntfIO *pInMsgIO; + void ioBlockedSignal(); // dummy // @@ -919,17 +740,58 @@ private: // caStatus searchFailResponse(const caHdr *pMsg); - caStatus searchResponse(casChannelI *pChan, const caHdr &msg, - gdd *pDesc, const caStatus status); + caStatus searchResponse(const caHdr &, const pvExistReturn &); + + caStatus asyncSearchResponse(casDGIntfIO &outMsgIO, + const caAddr &outAddr, const caHdr &msg, + const pvExistReturn &retVal); + caAddr fetchRespAddr(); + casDGIntfIO* fetchOutIntf(); + + + // + // IO depen + // + xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv, + bufSizeT &nByesRecv, caAddr &sender); + xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent, + bufSizeT &nBytesSent, const caAddr &recipient); + bufSizeT incommingBytesPresent() const; }; -#include // OS dependent +class casEventRegistry : private resTable { +public: + casEventRegistry(osiMutex &mutexIn) : + mutex(mutexIn), allocator(0), hasBeenInitialized(0) {} + + int init(); + ~casEventRegistry() + { + this->destroyAllEntries(); + } + casEventMask registerEvent (const char *pName); + + void show (unsigned level); + +private: + osiMutex &mutex; + unsigned allocator; + unsigned char hasBeenInitialized; + + casEventMask maskAllocator(); +}; + +#include "casIOD.h" // IO dependent +#include "casOSD.h" // OS dependent class casClientMon; class caServerI : - public caServerOS, public caServerIO, - public osiMutex, public ioBlockedList, + public osiMutex, // osiMutex must be first because it is used + // by ioBlockedList and casEventRegistry + public caServerOS, + public caServerIO, + public ioBlockedList, private uintResTable, public casEventRegistry { public: @@ -948,11 +810,6 @@ public: // casPVI *resIdToPV(const caResId &id); - // - // find the async IO associated with a resource id - // - casAsyncIO *resIdToAsyncIO(const caResId &id); - // // find the client monitor associated with a resource id // @@ -982,22 +839,17 @@ public: aitBool roomForNewChannel() const; // - // only for use with DG io - // + // send beacon and advance beacon timer + // void sendBeacon(); unsigned getDebugLevel() const { return debugLevel; } - void setDebugLevel(unsigned debugLevelIn) - { - this->debugLevel = debugLevelIn; - } - - inline caStatus pvExistTest (const casCtx &ctx, const char *pPVName, - gdd &canonicalPVName); + inline void setDebugLevel(unsigned debugLevelIn); + inline pvExistReturn pvExistTest (const casCtx &ctx, const char *pPVName); inline void pvExistTestCompletion(); inline aitBool pvExistTestPossible(); - casPVI *createPV(/* const */gdd &name); + casPVI *createPV(const char *pName); osiTime getBeaconPeriod() const { return this->beaconPeriod; } @@ -1005,44 +857,32 @@ public: inline casRes *lookupRes(const caResId &idIn, casResType type); - unsigned getPVMaxNameLength() const - { - return this->pvMaxNameLength; - } + inline unsigned getPVMaxNameLength() const; - caServer *getAdapter() - { - return &this->adapter; - } + inline caServer *getAdapter(); - //uintResTable &getResTable() {return *this;} + inline void installItem(casRes &res); - void installItem(casRes &res) - { - this->uintResTable::installItem(res); - } - - casRes *removeItem(casRes &res) - { - return this->uintResTable::remove(res); - } + inline casRes *removeItem(casRes &res); // // call virtual function in the interface class // - caServer * operator -> () - { - return this->getAdapter(); - } + inline caServer * operator -> (); - void connectCB(); + void connectCB(casIntfOS &); + inline aitBool ready(); + + caStatus addAddr(const caAddr &caAddr, int autoBeaconAddr, + int addConfigAddr); private: void advanceBeaconPeriod(); casDGOS dgClient; casCtx ctx; tsDLList clientList; + tsDLList intfList; resTable stringResTbl; osiTime beaconPeriod; caServer &adapter; @@ -1060,11 +900,11 @@ private: // the maximum number of characters in a pv name // default = none - required initialization parameter const unsigned maxSimultaneousIO; + + unsigned char haveBeenInitialized; }; #define CAServerConnectPendQueueSize 10 -const osiTime CAServerMaxBeaconPeriod (5.0 /* sec */); -const osiTime CAServerMinBeaconPeriod (1.0e-3 /* sec */); /* * If there is insufficent space to allocate an diff --git a/src/cas/io/bsdSocket/caServerIO.cc b/src/cas/io/bsdSocket/caServerIO.cc index 5150b9beb..ab093ce5c 100644 --- a/src/cas/io/bsdSocket/caServerIO.cc +++ b/src/cas/io/bsdSocket/caServerIO.cc @@ -5,22 +5,30 @@ // // // $Log$ +// Revision 1.2 1996/06/21 02:12:40 jhill +// SOLARIS port +// // Revision 1.1.1.1 1996/06/20 00:28:19 jhill // ca server installation // // +#include + #include #include -#ifdef SOLARIS -# include -#endif - -const unsigned caServerConnectPendQueueSize = 10u; +static char *getToken(char **ppString); int caServerIO::staticInitialized; +// +// caServerIO::~caServerIO() +// +caServerIO::~caServerIO() +{ +} + // // caServerIO::staticInit() // @@ -39,186 +47,124 @@ inline void caServerIO::staticInit() // // caServerIO::init() // -caStatus caServerIO::init() +caStatus caServerIO::init(caServerI &cas) { - caAddr serverAddr; - int yes = TRUE; - int status; - int len; - int port; + ENV_PARAM buf; + char *pStr; + char *pToken; + caStatus stat; + unsigned short port; + caAddr addr; + int autoBeaconAddr; caServerIO::staticInit(); - /* - * Setup the server socket - */ - this->sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (this->sock<0) { - return S_cas_noFD; - } + // + // first try for the server's private port number env var. + // If this available use the CA server port number (used by + // clients to find the server). If this also isnt available + // then use a hard coded default - CA_SERVER_PORT. + // + if (envParamIsEmpty(&EPICS_CAS_SERVER_PORT)) { + port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT); + } + else { + port = caFetchPortConfig(&EPICS_CAS_SERVER_PORT, CA_SERVER_PORT); + } - /* - * release the port in case we exit early - */ - status = setsockopt ( - this->sock, - SOL_SOCKET, - SO_REUSEADDR, - (char *) &yes, - sizeof (yes)); - if (status<0) { - ca_printf("CAS: server set SO_REUSEADDR failed?\n", - strerror(SOCKERRNO)); - return S_cas_internal; - } + memset((char *)&addr,0,sizeof(addr)); + addr.sa.sa_family = AF_INET; + addr.in.sin_port = ntohs (port); - memset ((char *)&serverAddr, '\0', sizeof(serverAddr)); - serverAddr.sa.sa_family = AF_INET; - serverAddr.in.sin_addr.s_addr = INADDR_ANY; - port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT); - serverAddr.in.sin_port = ntohs (port); - status = bind( - this->sock, - &serverAddr.sa, - sizeof(serverAddr.sa)); - if (status<0) { - if (SOCKERRNO == EADDRINUSE) { - // - // force assignement of a default port - // (so the getsockname() call below will - // work correctly) - // - serverAddr.in.sin_port = ntohs (0); - status = bind( - this->sock, - &serverAddr.sa, - sizeof(serverAddr.sa)); - if (status<0) { - ca_printf ( - "CAS: default bind failed because \"%s\"\n", - strerror(SOCKERRNO)); - return S_cas_portInUse; + pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, + sizeof(buf.dflt), buf.dflt); + if (strstr(pStr,"no")||strstr(pStr,"NO")) { + autoBeaconAddr = FALSE; + } + else { + autoBeaconAddr = TRUE; + } + + // + // bind to the the interfaces specified - otherwise wildcard + // with INADDR_ANY and allow clients to attach from any interface + // + pStr = envGetConfigParam(&EPICS_CAS_INTF_ADDR_LIST, + sizeof(buf.dflt), buf.dflt); + if (pStr) { + int configAddrOnceFlag = TRUE; + stat = S_cas_noInterface; + while ( (pToken = getToken(&pStr)) ) { + addr.in.sin_addr.s_addr = inet_addr(pToken); + if (addr.in.sin_addr.s_addr == ~0ul) { + ca_printf( + "%s: Parsing '%s'\n", + __FILE__, + EPICS_CAS_INTF_ADDR_LIST.name); + ca_printf( + "\tBad internet address format: '%s'\n", + pToken); + continue; } + stat = cas.addAddr(addr, autoBeaconAddr, configAddrOnceFlag); + if (stat) { + errMessage(stat, NULL); + break; + } + configAddrOnceFlag = FALSE; } - else { - ca_printf("CAS: bind failed because \"%s\"\n", - strerror(SOCKERRNO)); - return S_cas_portInUse; - } - } + } + else { + addr.in.sin_addr.s_addr = INADDR_ANY; + stat = cas.addAddr(addr, autoBeaconAddr, TRUE); + if (stat) { + errMessage(stat, NULL); + } + } - len = sizeof (this->addr.sa); - status = getsockname ( - this->sock, - &this->addr.sa, - &len); - if (status<0) { - ca_printf("CAS: getsockname failed because: %s\n", - strerror(SOCKERRNO)); - return S_cas_internal; - } - - // - // be sure of this now so that we can fetch the IP - // address and port number later - // - assert (this->addr.sa.sa_family == AF_INET); - - status = listen(this->sock, caServerConnectPendQueueSize); - if(status < 0) { - ca_printf("CAS: Listen error %s\n",strerror(SOCKERRNO)); - return S_cas_internal; - } - this->sockState = casOnLine; - return S_cas_success; -} - -// -// caServerIO::serverPortNumber() -// -unsigned caServerIO::serverPortNumber() const -{ - return (unsigned) ntohs(this->addr.in.sin_port); + return stat; } // // caServerIO::show() // -void caServerIO::show (unsigned level) +void caServerIO::show (unsigned /* level */) const { printf ("caServerIO at %x\n", (unsigned) this); - if (level>1u) { - printf ("\tsock = %d, state = %d\n", - this->sock, this->sockState); - } } // -// caServerIO::newDGIO() +// getToken() // -casMsgIO *caServerIO::newDGIO() const +static char *getToken(char **ppString) { - casDGIO *pDG; - - pDG = new casDGIO(); - if (!pDG) { - return pDG; - } - - return pDG; -} - -// -// caServerIO::newStreamIO() -// -casMsgIO *caServerIO::newStreamIO() const -{ - caAddr newAddr; - SOCKET newSock; - int length; - - length = sizeof(newAddr.sa); - newSock = accept(this->sock, &newAddr.sa, &length); - if (newSock<0) { - if (SOCKERRNO!=EWOULDBLOCK) { - ca_printf( - "CAS: %s accept error %s\n", - __FILE__, - strerror(SOCKERRNO)); - } + char *pToken; + char *pStr; + + pToken = *ppString; + while(isspace(*pToken)&&*pToken){ + pToken++; + } + + pStr = pToken; + while(!isspace(*pStr)&&*pStr){ + pStr++; + } + + if(isspace(*pStr)){ + *pStr = '\0'; + *ppString = pStr+1; + } + else{ + *ppString = pStr; + assert(*pStr == '\0'); + } + + if(*pToken){ + return pToken; + } + else{ return NULL; } - else if (sizeof(newAddr.sa)>(size_t)length) { - ca_printf("CAS: accept returned bad address len?\n"); - return NULL; - } - - return new casStreamIO(newSock, newAddr); } -// -// caServerIO::setNonBlocking() -// -void caServerIO::setNonBlocking() -{ - int status; - int yes = TRUE; - - status = socket_ioctl(this->sock, FIONBIO, &yes); - if (status<0) { - ca_printf( - "%s:CAS: server non blocking IO set fail because \"%s\"\n", - __FILE__, strerror(SOCKERRNO)); - this->sockState = casOffLine; - } -} - -// -// caServerIO::getFD() -// -int caServerIO::getFD() const -{ - return this->sock; -} - - diff --git a/src/cas/io/bsdSocket/casDGIO.cc b/src/cas/io/bsdSocket/casDGIO.cc index 17c6385a8..98e8ec911 100644 --- a/src/cas/io/bsdSocket/casDGIO.cc +++ b/src/cas/io/bsdSocket/casDGIO.cc @@ -28,377 +28,22 @@ * History */ -// -// -// Should I fetch the MTU from the outgoing interface? -// -// - #include -#ifdef SOLARIS -# include -#endif +#include // in line func for dgInBuf // -// casDGIO::casDGIO() +// casDGIO::clientHostName() // -casDGIO::casDGIO() +void casDGIO::clientHostName (char *pBufIn, unsigned bufSizeIn) const { - this->sockState=casOffLine; - ellInit(&this->destAddrList); - memset((char *)&this->lastRecvAddr, '\0', sizeof(this->lastRecvAddr)); - this->sock = -1; - this->lastRecvAddrInit = FALSE; -} - -// -// casDGIO::init() -// -caStatus casDGIO::init() -{ - int yes = TRUE; - caAddr serverAddr; - int status; - unsigned short port; - - this->sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (this->sock < 0) { - errMessage(S_cas_noMemory, - "CAS: unable to create cast socket\n"); - return S_cas_noMemory; + if (this->hasAddress()) { + const caAddr addr = this->getSender(); + ipAddrToA (&addr.in, pBufIn, bufSizeIn); } - - status = setsockopt( - this->sock, - SOL_SOCKET, - SO_BROADCAST, - (char *)&yes, - sizeof(yes)); - if (status<0) { - errMessage(S_cas_internal, - "CAS: unable to set up cast socket\n"); - return S_cas_internal; - } - - /* - * release the port in case we exit early. Also if - * on a kernel with MULTICAST mods then we can have - * two UDP servers on the same port number (requires - * setting SO_REUSEADDR prior to the bind step below). - */ - status = setsockopt( - this->sock, - SOL_SOCKET, - SO_REUSEADDR, - (char *) &yes, - sizeof (yes)); - if (status<0) { - errMessage(S_cas_internal, - "CAS: unable to set SO_REUSEADDR on UDP socket?\n"); - } - - memset ((char *)&serverAddr, '\0', sizeof(serverAddr)); - serverAddr.sa.sa_family = AF_INET; - serverAddr.in.sin_addr.s_addr = INADDR_ANY; - port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT); - serverAddr.in.sin_port = htons (port); - - status = bind( - this->sock, - &serverAddr.sa, - sizeof (serverAddr.sa)); - if (status<0) { - errPrintf(S_cas_portInUse, - __FILE__, __LINE__, - "CAS: bind to the broadcast port = %u fail: %s\n", - (unsigned) port, - strerror(SOCKERRNO)); - return S_cas_portInUse; - } - - port = caFetchPortConfig(&EPICS_CA_REPEATER_PORT, CA_REPEATER_PORT); - - caDiscoverInterfaces( - &this->destAddrList, - this->sock, - port); - - caAddConfiguredAddr( - &this->destAddrList, - &EPICS_CA_ADDR_LIST, - this->sock, - port); - -# if defined(DEBUG) - caPrintAddrList(&destAddrList); -# endif - this->sockState=casOnLine; - - return S_cas_success; -} - -// -// use an initialize routine ? -// -casDGIO::~casDGIO() -{ - caAddrNode *pAddr; - - if(this->sock>=0){ - socket_close(this->sock); - } - - while ( (pAddr = (caAddrNode *)ellGet(&this->destAddrList)) ) { - free((char *)pAddr); - } -} - -// -// casDGIO::hostName() -// -void casDGIO::hostNameFromAddr (char *pBuf, unsigned bufSize) -{ - hostNameFromIPAddr(&this->lastRecvAddr, pBuf, bufSize); -} - -// -// casDGIO::show() -// -void casDGIO::osdShow (unsigned level) const -{ - printf ("casDGIO at %x\n", (unsigned) this); - if (level>=1u) { - printf( - "client address=%x, port=%x\n", - (unsigned) ntohl(this->lastRecvAddr.in.sin_addr.s_addr), - ntohs(this->lastRecvAddr.in.sin_port)); - } -} - -// -// casDGIO::xSetNonBlocking() -// -void casDGIO::xSetNonBlocking() -{ - int status; - int yes = TRUE; - - if (this->sockState!=casOnLine) { - return; - } - - status = socket_ioctl(this->sock, FIONBIO, &yes); - if (status<0) { - ca_printf("%s:CAS: UDP non blocking IO set fail because \"%s\"\n", - __FILE__, strerror(SOCKERRNO)); - this->sockState = casOffLine; - } -} - -// -// casDGIO::osdRecv() -// -xRecvStatus casDGIO::osdRecv(char *pBuf, bufSizeT size, bufSizeT &actualSize) -{ - int status; - int addrSize; - - if (this->sockState!=casOnLine) { - return xRecvDisconnect; - } - - addrSize = sizeof(this->lastRecvAddr.sa); - status = recvfrom(this->sock, pBuf, size, 0, - &this->lastRecvAddr.sa, &addrSize); - if (status<0) { - if(SOCKERRNO == EWOULDBLOCK){ - actualSize = 0u; - return xRecvOK; - } - else { - ca_printf("CAS: UDP recv error",strerror(SOCKERRNO)); - actualSize = 0u; - return xRecvOK; - } - } - - this->lastRecvAddrInit = TRUE; - -#if 0 - if(pRsrv->CASDEBUG>1){ - char buf[64]; - - (*pRsrv->osm.hostName) - (&pCastClient->addr, buf, sizeof(buf)); - ca_printf( - "CAS: incomming %d byte UDP msg from %s\n", - pCastClient->pRecv->cnt, - buf); - } -#endif - - actualSize = (bufSizeT) status; - return xRecvOK; -} - -// -// casDGIO::osdSend() -// -xSendStatus casDGIO::osdSend(const char *pBuf, bufSizeT size, - bufSizeT &actualSize) -{ - int status; - int anerrno; - - assert(this->lastRecvAddrInit); - -#if 0 - if(this->pCAS->debugLevel>2u){ - char buf[64]; - - (*pCAS->osm.hostName) ( - &this->addr, - buf, - sizeof(buf)); - ca_printf( - "CAS: Sending a %d byte reply to %s\n", - this->pSend->stk, - buf); - } -#endif - - if (this->sockState!=casOnLine) { - return xSendDisconnect; - } - - if (size==0u) { - actualSize = 0u; - return xSendOK; - } - - // - // (char *) cast below is for brain dead wrs prototype - // - status = sendto(this->sock, (char *) pBuf, size, 0, - &this->lastRecvAddr.sa, - sizeof(this->lastRecvAddr.sa)); - if (status>0) { - if (size != (unsigned) status) { - printf ("CAS: partial UDP msg discarded??\n"); - } - } - else if (status==0) { - this->sockState = casOffLine; - printf ("CAS: UDP send returns zero??\n"); - return xSendDisconnect; - } - else { - anerrno = SOCKERRNO; - - if (anerrno != EWOULDBLOCK) { - ca_printf( - "CAS: UDP send failed \"%s\"\n", - strerror(anerrno)); - } - } - - actualSize = size; - return xSendOK; -} - - -// -// casDGIO::sendBeacon() -// -void casDGIO::sendBeacon(char &msg, unsigned length, aitUint32 &m_avail) -{ - caAddrNode *pAddr; - int status; - - if (this->sockState!=casOnLine) { - return; - } - - for( pAddr = (caAddrNode *)ellFirst(&this->destAddrList); - pAddr; - pAddr = (caAddrNode *)ellNext(&pAddr->node)) { - - m_avail = htonl(pAddr->srcAddr.in.sin_addr.s_addr); - - status = sendto( - this->sock, - &msg, - length, - 0, - &pAddr->destAddr.sa, - sizeof(pAddr->destAddr.sa)); - if (status < 0) { - ca_printf( - "CAS:beacon error was \"%s\" at addr=%x sock=%d\n", - strerror(SOCKERRNO), - pAddr->destAddr.in.sin_addr.s_addr, - this->sock); + else { + if (bufSizeIn>=1u) { + pBufIn[0u] = '\0'; } } } -// -// casDGIO::optimumBufferSize() -// -// this returns 9000 on the suns - perhaps this will result in -// to much IP fragmentation -// -bufSizeT casDGIO::optimumBufferSize () -{ - -#if 1 - // - // must update client before the message size can be - // increased here - // - return MAX_UDP; -#else - int n; - int size; - int status; - - if (this->sockState!=casOnLine) { - return MAX_UDP; - } - - /* fetch the TCP send buffer size */ - n = sizeof(size); - status = getsockopt( - this->sock, - SOL_SOCKET, - SO_SNDBUF, - (char *)&size, - &n); - if(status < 0 || n != sizeof(size)){ - size = MAX_UDP; - } - - if (size<=0) { - size = MAX_UDP; - } - return (bufSizeT) size; -#endif -} - - -// -// casDGIO::state() -// -casIOState casDGIO::state() const -{ - return this->sockState; -} - -// -// casDGIO::getFileDescriptor() -// -int casDGIO::getFileDescriptor() const -{ - return this->sock; -} - diff --git a/src/cas/io/bsdSocket/casIOD.h b/src/cas/io/bsdSocket/casIOD.h index 3286438b5..eb5add5db 100644 --- a/src/cas/io/bsdSocket/casIOD.h +++ b/src/cas/io/bsdSocket/casIOD.h @@ -7,6 +7,9 @@ // Some BSD calls have crept in here // // $Log$ +// Revision 1.5 1996/09/16 18:25:15 jhill +// vxWorks port changes +// // Revision 1.4 1996/09/04 20:29:08 jhill // removed os depen stuff // @@ -24,115 +27,184 @@ #ifndef includeCASIODH #define includeCASIODH - -#include - -// ca -#include - void hostNameFromIPAddr (const caAddr *pAddr, char *pBuf, unsigned bufSize); -class caServerIO { -public: - caServerIO() : sockState(casOffLine), sock(-1) {} - ~caServerIO() - { - if (this->sock>=0 && this->sockState==casOnLine) { - socket_close(this->sock); - } - } - caStatus init(); //constructor does not return status - - // - // show status of IO subsystem - // - void show (unsigned level); - - int getFD() const; - - void setNonBlocking(); - - unsigned serverPortNumber() const; - - // - // called when we expect that a virtual circuit for a - // client can be created - // - casMsgIO *newStreamIO() const; - - // - // called to create datagram IO - // - casMsgIO *newDGIO() const; +class casDGClient; + +// +// casDGIntfIO +// +class casDGIntfIO { +public: + casDGIntfIO (casDGClient &clientIn); + caStatus init(const caAddr &addr, unsigned connectWithThisPort, + int autoBeaconAddr=TRUE, int addConfigBeaconAddr=FALSE, + int useBroadcastAddr=FALSE, casDGIntfIO *pAltOutIn=NULL); + virtual ~casDGIntfIO(); + + int getFD() const; + void xSetNonBlocking(); + void sendBeacon(char &msg, bufSizeT length, aitUint32 &m_avail); + casIOState state() const; + void clientHostName (char *pBuf, unsigned bufSize) const; + + xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual, const caAddr &addr); + xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual, caAddr &addr); + void osdShow (unsigned level) const; + + static bufSizeT optimumBufferSize (); + + // + // The server's port number + // (to be used for connection requests) + // + unsigned serverPortNumber(); + + virtual caStatus start()=0; // OS specific + + inline void processDG(); + +private: + ELLLIST beaconAddrList; + casDGIntfIO *pAltOutIO; + casDGClient &client; + SOCKET sock; + casIOState sockState; + aitInt16 connectWithThisPort; +}; + +struct ioArgsToNewStreamIO { + caAddr addr; + SOCKET sock; +}; + +// +// casDGIO +// +class casDGIO : public casDGClient { +public: + casDGIO(caServerI &cas) : + casDGClient(cas) {} + + // + // clientHostName() + // + void clientHostName (char *pBufIn, unsigned bufSizeIn) const; +}; + +// +// casStreamIO +// +class casStreamIO : public casStrmClient { +public: + casStreamIO(caServerI &cas, const ioArgsToNewStreamIO &args); + caStatus init(); + ~casStreamIO(); + + int getFD() const; + void xSetNonBlocking(); + + casIOState state() const; + void clientHostName (char *pBuf, unsigned bufSize) const; + + xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual); + xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual); + + xBlockingStatus blockingState() const; + + bufSizeT incommingBytesPresent() const; + + static bufSizeT optimumBufferSize (); + + void osdShow (unsigned level) const; + + // + // The server's port number + // (to be used for connection requests) + // + unsigned serverPortNumber(); + + const caAddr &getAddr() + { + return addr; + } private: casIOState sockState; SOCKET sock; caAddr addr; + xBlockingStatus blockingFlag; +}; + +class caServerIO; +class casDGClient; + +class casStreamOS; + +// +// casIntfIO +// +class casIntfIO { +public: + casIntfIO(); + //constructor does not return status + caStatus init(const caAddr &addr, casDGClient &dgClientIn, + int autoBeaconAddr, int addConfigBeaconAddr); + virtual ~casIntfIO(); + void show(unsigned level) const; + + unsigned portNumber() const; + + int getFD() const; + + void setNonBlocking(); + + // + // called when we expect that a virtual circuit for a + // client can be created + // + casStreamOS *newStreamClient(caServerI &cas) const; + + virtual casDGIntfIO *newDGIntfIO (casDGClient &dgClientIn) const = 0; + + void requestBeacon(); +private: + casDGIntfIO *pNormalUDP; // attached to this intf's addr + casDGIntfIO *pBCastUDP; // attached to this intf's broadcast addr + SOCKET sock; + caAddr addr; +}; + +// +// caServerIO +// +class caServerIO { +public: + caStatus init(caServerI &cas); //constructor does not return status + ~caServerIO(); + + // + // show status of IO subsystem + // + void show (unsigned level) const; + +private: + // // static member data // - static int staticInitialized; + static int staticInitialized; // // static member func // static inline void staticInit(); }; -class casStreamIO : public casMsgIO { -public: - casStreamIO(const SOCKET s, const caAddr &a); - caStatus init(); - ~casStreamIO(); - - int getFileDescriptor() const; - void xSetNonBlocking(); - bufSizeT optimumBufferSize (); - - casIOState state() const; - void hostNameFromAddr (char *pBuf, unsigned bufSize); - - xSendStatus osdSend (const char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual); - xRecvStatus osdRecv (char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual); - void osdShow (unsigned level) const; - - bufSizeT incommingBytesPresent() const; -private: - casIOState sockState; - SOCKET sock; - caAddr addr; -}; - -class casDGIO : public casMsgIO { -public: - casDGIO(); - caStatus init(); - ~casDGIO(); - - int getFileDescriptor() const; - void xSetNonBlocking(); - bufSizeT optimumBufferSize (); - void sendBeacon(char &msg, bufSizeT length, - aitUint32 &m_avail); - casIOState state() const; - void hostNameFromAddr (char *pBuf, unsigned bufSize); - - xSendStatus osdSend (const char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual); - xRecvStatus osdRecv (char *pBuf, - bufSizeT nBytesReq, bufSizeT &nBytesActual); - void osdShow (unsigned level) const; -private: - ELLLIST destAddrList; - caAddr lastRecvAddr; - SOCKET sock; - casIOState sockState; - char lastRecvAddrInit; -}; - // no additions below this line #endif // includeCASIODH diff --git a/src/cas/io/bsdSocket/casStreamIO.cc b/src/cas/io/bsdSocket/casStreamIO.cc index 892ad9d4e..3467cd21f 100644 --- a/src/cas/io/bsdSocket/casStreamIO.cc +++ b/src/cas/io/bsdSocket/casStreamIO.cc @@ -5,6 +5,9 @@ // // // $Log$ +// Revision 1.5 1996/09/16 18:25:16 jhill +// vxWorks port changes +// // Revision 1.4 1996/07/24 22:03:36 jhill // fixed net proto for gnu compiler // @@ -20,29 +23,15 @@ // #include -#ifdef SOLARIS -# include -#endif -#include -#include -#include -// -// the SUNOS4 and vxWorks5.2 prototypes are trad C -// -#if !defined(SUNOS4) && !defined(vxWorks) -#include -#else -extern "C" { -char * inet_ntoa(struct in_addr); -} -#endif // // casStreamIO::casStreamIO() // -casStreamIO::casStreamIO(const SOCKET s, const caAddr &a) : - sockState(casOffLine), sock(s), addr(a) +casStreamIO::casStreamIO(caServerI &cas, const ioArgsToNewStreamIO &args) : + casStrmClient(cas), + sockState(casOffLine), sock(args.sock), addr(args.addr), + blockingFlag(xIsBlocking) { assert (sock>=0); } @@ -69,8 +58,7 @@ caStatus casStreamIO::init() if (status<0) { ca_printf( "CAS: %s TCP_NODELAY option set failed %s\n", - __FILE__, - strerror(SOCKERRNO)); + __FILE__, strerror(SOCKERRNO)); return S_cas_internal; } @@ -87,8 +75,7 @@ caStatus casStreamIO::init() if (status<0) { ca_printf( "CAS: %s SO_KEEPALIVE option set failed %s\n", - __FILE__, - strerror(SOCKERRNO)); + __FILE__, strerror(SOCKERRNO)); return S_cas_internal; } #ifdef MATCHING_BUFFER_SIZES @@ -123,7 +110,7 @@ caStatus casStreamIO::init() #endif this->sockState = casOnLine; - return S_cas_success; + return this->casStrmClient::init(); } @@ -134,7 +121,6 @@ casStreamIO::~casStreamIO() { if (sock>=0) { close(this->sock); -printf("closing sock=%d\n", this->sock); } } @@ -142,26 +128,11 @@ printf("closing sock=%d\n", this->sock); // // casStreamIO::osdSend() // -xSendStatus casStreamIO::osdSend(const char *pBuf, bufSizeT nBytesReq, +xSendStatus casStreamIO::osdSend(const char *pInBuf, bufSizeT nBytesReq, bufSizeT &nBytesActual) { int status; -#if 0 - if(this->pCAS->debugLevel>2u){ - char buf[64]; - - (*pCAS->osm.hostName) ( - &this->addr, - buf, - sizeof(buf)); - ca_printf( - "CAS: Sending a %d byte reply to %s\n", - this->pSend->stk, - buf); - } -#endif - if (this->sockState!=casOnLine) { return xSendDisconnect; } @@ -173,7 +144,7 @@ xSendStatus casStreamIO::osdSend(const char *pBuf, bufSizeT nBytesReq, status = send ( this->sock, - (char *) pBuf, + (char *) pInBuf, nBytesReq, 0); if (status == 0) { @@ -197,7 +168,7 @@ xSendStatus casStreamIO::osdSend(const char *pBuf, bufSizeT nBytesReq, // // casStreamIO::osdRecv() // -xRecvStatus casStreamIO::osdRecv(char *pBuf, bufSizeT nBytes, +xRecvStatus casStreamIO::osdRecv(char *pInBuf, bufSizeT nBytes, bufSizeT &nBytesActual) { int nchars; @@ -206,12 +177,14 @@ xRecvStatus casStreamIO::osdRecv(char *pBuf, bufSizeT nBytes, return xRecvDisconnect; } - nchars = recv(this->sock, pBuf, nBytes, 0); + nchars = recv(this->sock, pInBuf, nBytes, 0); if (nchars==0) { this->sockState = casOffLine; return xRecvDisconnect; } else if (nchars<0) { + char buf[64]; + /* * normal conn lost conditions */ @@ -226,9 +199,10 @@ xRecvStatus casStreamIO::osdRecv(char *pBuf, bufSizeT nBytes, break; default: + ipAddrToA(&this->addr.in, buf, sizeof(buf)); ca_printf( - "CAS: client disconnect because \"%s\"\n", - strerror(SOCKERRNO)); + "CAS: client %s disconnected because \"%s\"\n", + buf, strerror(SOCKERRNO)); break; } this->sockState = casOffLine; @@ -246,10 +220,11 @@ void casStreamIO::osdShow (unsigned level) const { printf ("casStreamIO at %x\n", (unsigned) this); if (level>1u) { + char buf[64]; + ipAddrToA(&this->addr.in, buf, sizeof(buf)); printf ( - "client address=%x, port=%x\n", - (unsigned) ntohl(this->addr.in.sin_addr.s_addr), - ntohs(this->addr.in.sin_port)); + "client=%s, port=%x\n", + buf, ntohs(this->addr.in.sin_port)); } } @@ -267,13 +242,24 @@ void casStreamIO::xSetNonBlocking() } status = socket_ioctl(this->sock, FIONBIO, &yes); - if (status<0) { + if (status>=0) { + this->blockingFlag = xIsntBlocking; + } + else { ca_printf("%s:CAS: TCP non blocking IO set fail because \"%s\"\n", __FILE__, strerror(SOCKERRNO)); this->sockState = casOffLine; } } +// +// casStreamIO::blockingState() +// +xBlockingStatus casStreamIO::blockingState() const +{ + return this->blockingFlag; +} + // // casStreamIO::incommingBytesPresent() @@ -298,76 +284,28 @@ bufSizeT casStreamIO::incommingBytesPresent() const // -// casStreamIO::hostName() +// casStreamIO::clientHostName() // -void casStreamIO::hostNameFromAddr(char *pBuf, unsigned bufSize) +void casStreamIO::clientHostName (char *pInBuf, unsigned bufSizeIn) const { - hostNameFromIPAddr(&this->addr, pBuf, bufSize); -} - - -// -// hostNameFromIPAddr() -// -void hostNameFromIPAddr (const caAddr *pAddr, - char *pBuf, unsigned bufSize) -{ - char *pName; - - assert (bufSize>0U); - - if (pAddr->sa.sa_family != AF_INET) { - strncpy (pBuf, "UKN ADDR FAMILY", bufSize); - } - else { - int port = ntohs(pAddr->in.sin_port); -# define maxPortDigits 15U - char tmp[maxPortDigits+1]; - unsigned size; - -#if 0 // bypass this because of problems with SUNOS4 header files and C++ - struct hostent *ent; - - ent = gethostbyaddr( - (char *) &pAddr->in.sin_addr.s_addr, - sizeof(pAddr->in.sin_addr.s_addr), - AF_INET); - if (ent) { - pName = ent->h_name; - } - else { - pName = inet_ntoa (pAddr->in.sin_addr); - } -#else - pName = inet_ntoa (pAddr->in.sin_addr); -#endif - - assert (bufSize>maxPortDigits); - size = bufSize - maxPortDigits; - strncpy (pBuf, pName, size); - pBuf[size] = '\0'; - sprintf (tmp, ".%d", port); - strncat (pBuf, tmp, maxPortDigits); - } - pBuf[bufSize-1] = '\0'; - assert(strlen(pBuf)<=bufSize); + ipAddrToA (&this->addr.in, pInBuf, bufSizeIn); } // // casStreamIO:::optimumBufferSize() // -bufSizeT casStreamIO::optimumBufferSize () +bufSizeT casStreamIO::optimumBufferSize () { - if (this->sockState!=casOnLine) { - return 0x400; - } - #if 0 int n; int size; int status; + if (this->sockState!=casOnLine) { + return MAX_TCP; + } + /* fetch the TCP send buffer size */ n = sizeof(size); status = getsockopt( @@ -392,14 +330,13 @@ printf("the tcp buf size is %d\n", size); } // -// casStreamIO::getFileDescriptor() +// casStreamIO::getFD() // -int casStreamIO::getFileDescriptor() const +int casStreamIO::getFD() const { - return sock; + return this->sock; } - // // casStreamIO::state() // diff --git a/src/cas/os/posix/caServerOS.cc b/src/cas/os/posix/caServerOS.cc deleted file mode 100644 index 9720b1eac..000000000 --- a/src/cas/os/posix/caServerOS.cc +++ /dev/null @@ -1,116 +0,0 @@ - -/* - * - * caServerOS.c - * $Id$ - * - * - * $Log$ - * Revision 1.1.1.1 1996/06/20 00:28:06 jhill - * ca server installation - * - * - */ - - -// -// CA server -// -#include - -#define nSecPerUSec 1000 - -// -// aServerOS::operator -> () -// -inline caServerI * caServerOS::operator -> () -{ - return &this->cas; -} - -// -// casBeaconTimer::expire() -// -void casBeaconTimer::expire() -{ - os->sendBeacon (); -} - -// -// casBeaconTimer::again() -// -osiBool casBeaconTimer::again() -{ - return osiTrue; -} - -// -// casBeaconTimer::delay() -// -const osiTime casBeaconTimer::delay() -{ - return os->getBeaconPeriod(); -} - - -// -// caServerOS::init() -// -caStatus caServerOS::init() -{ - (*this)->setNonBlocking(); - - this->pRdReg = new casServerReg(*this); - if (!this->pRdReg) { - return S_cas_noMemory; - } - - this->pBTmr = new casBeaconTimer((*this)->getBeaconPeriod(), *this); - if (!this->pBTmr) { - ca_printf("CAS: Unable to start server beacon\n"); - return S_cas_noMemory; - } - - return S_cas_success; -} - - -// -// caServerOS::~caServerOS() -// -caServerOS::~caServerOS() -{ - if (this->pRdReg) { - delete this->pRdReg; - } - if (this->pBTmr) { - delete this->pBTmr; - } -} - - -// -// casServerReg::callBack() -// -void casServerReg::callBack() -{ - assert(os.pRdReg); - os->connectCB(); -} - -// -// casServerReg::~casServerReg() -// -casServerReg::~casServerReg() -{ - this->os.pRdReg = NULL; -} - -// -// caServerOS::getFD() -// -int caServerOS::getFD() -{ - return cas.caServerIO::getFD(); -} - diff --git a/src/cas/os/posix/casClientOS.h b/src/cas/os/posix/casClientOS.h deleted file mode 100644 index 3e5db6a0b..000000000 --- a/src/cas/os/posix/casClientOS.h +++ /dev/null @@ -1,131 +0,0 @@ - -class casStreamWriteReg; -class casStreamReadReg; -class casStreamEvWakeup; - -// -// casStreamOS -// -class casStreamOS : public casStrmClient { - friend class casStreamReadReg; - friend class casStreamWriteReg; - friend class casStreamEvWakeup; -public: - casStreamOS(caServerI &, casMsgIO &); - caStatus init(); - ~casStreamOS(); - - // - // process any incomming messages - // - casProcCond processInput(); - caStatus start(); - - void recvCB(); - void sendCB(); - - void sendBlockSignal(); - - void ioBlockedSignal(); - - void eventSignal(); - void eventFlush(); - - void show(unsigned level); -private: - casStreamWriteReg *pWtReg; - casStreamReadReg *pRdReg; - casStreamEvWakeup *pEvWk; - unsigned sendBlocked:1; - // - // - // - void armSend (); - void armRecv (); - void disarmSend(); - void disarmRecv(); -}; - -// -// casStreamReadReg -// -class casStreamReadReg : public fdReg { -public: - casStreamReadReg (casStreamOS &osIn) : - os (osIn), - fdReg (osIn.getFD(), fdrRead) {} - ~casStreamReadReg (); - - void show (unsigned level); -private: - casStreamOS &os; - - void callBack (); -}; - -// -// casStreamWriteReg -// -class casStreamWriteReg : public fdReg { -public: - casStreamWriteReg (casStreamOS &osIn) : - os (osIn), fdReg (osIn.getFD(), fdrWrite, TRUE) {} - ~casStreamWriteReg (); - - void show (unsigned level); -private: - casStreamOS &os; - - void callBack (); -}; - -class casDGReadReg; -class casDGEvWakeup; - -// -// casDGOS -// -class casDGOS : public casDGClient { - friend class casDGReadReg; - friend class casDGEvWakeup; -public: - casDGOS(caServerI &cas); - caStatus init(); - ~casDGOS(); - - // - // process any incomming messages - // - casProcCond processInput(); - caStatus start(); - - void recvCB(); - void sendCB(); - - void sendBlockSignal() {} - - void eventSignal(); - void eventFlush(); - - void show(unsigned level); -private: - casDGReadReg *pRdReg; - casDGEvWakeup *pEvWk; -}; - -// -// casDGReadReg -// -class casDGReadReg : public fdReg { -public: - casDGReadReg (casDGOS &osIn) : - os (osIn), fdReg (osIn.getFD(), fdrRead) {} - ~casDGReadReg (); - - void show (unsigned level); -private: - casDGOS &os; - - void callBack (); -}; - diff --git a/src/cas/os/posix/casDGOS.cc b/src/cas/os/posix/casDGOS.cc deleted file mode 100644 index 87aa8f4af..000000000 --- a/src/cas/os/posix/casDGOS.cc +++ /dev/null @@ -1,196 +0,0 @@ - -/* - * - * casDGOS.c - * $Id$ - * - * - * $Log$ - * Revision 1.2 1996/08/05 19:29:25 jhill - * os depen code now smaller - * - * Revision 1.1.1.1 1996/06/20 00:28:06 jhill - * ca server installation - * - * - */ - -// -// CA server -// -#include -#include // casClient inline func - -class casDGEvWakeup : public osiTimer { -public: - casDGEvWakeup(casDGOS &osIn) : - osiTimer(osiTime(0.0)), os(osIn) {} - ~casDGEvWakeup() - { - os.pEvWk = NULL; - } - void expire(); - void show (unsigned level); - - const char *name() - { - return "casDGEvWakeup"; - } -private: - casDGOS &os; -}; - -// -// casDGEvWakeup::show() -// -void casDGEvWakeup::show(unsigned level) -{ - this->osiTimer::show(level); - printf("casDGEvWakeup at %x\n", (unsigned) this); -} - -// -// casDGEvWakeup::expire() -// -void casDGEvWakeup::expire() -{ - casProcCond cond; - cond = this->os.eventSysProcess(); - if (cond != casProcOk) { - // - // if "this" is being used above this - // routine on the stack then problems - // will result if we delete "this" here - // - // delete &this->os; - printf("DG event sys process failed\n"); - } -} - -// -// casDGOS::eventSignal() -// -void casDGOS::eventSignal() -{ - if (!this->pEvWk) { - this->pEvWk = new casDGEvWakeup(*this); - if (!this->pEvWk) { - errMessage(S_cas_noMemory, - "casDGOS::eventSignal()"); - } - } -} - -// -// casDGOS::eventFlush() -// -void casDGOS::eventFlush() -{ - this->flush(); -} - - -// -// casDGOS::casDGOS() -// -casDGOS::casDGOS(caServerI &cas) : - casDGClient(cas), - pRdReg(NULL), - pEvWk(NULL) -{ -} - -// -// casDGOS::init() -// -caStatus casDGOS::init() -{ - caStatus status; - - // - // init the base classes - // - status = this->casDGClient::init(); - - return status; -} - - -// -// casDGOS::~casDGOS() -// -casDGOS::~casDGOS() -{ - if (this->pRdReg) { - delete this->pRdReg; - } - if (this->pEvWk) { - delete this->pEvWk; - } -} - -// -// casDGOS::show() -// -void casDGOS::show(unsigned level) -{ - this->casDGClient::show(level); - printf ("casDGOS at %x\n", (unsigned) this); - if (this->pRdReg) { - this->pRdReg->show(level); - } - if (this->pEvWk) { - this->pEvWk->show(level); - } -} - - -/* - * casClientStart () - */ -caStatus casDGOS::start() -{ - this->pRdReg = new casDGReadReg (*this); - if (!this->pRdReg) { - return S_cas_noMemory; - } - return S_cas_success; -} - - -/* - * casDGOS::processInput () - * - a noop - */ -casProcCond casDGOS::processInput () -{ - return casProcOk; -} - -// -// casDGReadReg::callBack() -// -void casDGReadReg::callBack() -{ - assert (os.pRdReg); - - os.process(); -} - -// -// casDGReadReg::~casDGReadReg() -// -casDGReadReg::~casDGReadReg() -{ - this->os.pRdReg = NULL; -} - -// -// casDGReadReg::show() -// -void casDGReadReg::show(unsigned level) -{ - this->fdReg::show(level); - printf("casDGReadReg at %x\n", (unsigned) this); -} - diff --git a/src/cas/os/posix/casOSD.h b/src/cas/os/posix/casOSD.h deleted file mode 100644 index 11f73fe8e..000000000 --- a/src/cas/os/posix/casOSD.h +++ /dev/null @@ -1,113 +0,0 @@ -// -// $Id$ -// -// casOSD.h - Channel Access Server OS Dependent for posix -// -// -// Some BSD calls have crept in here -// -// $Log$ -// Revision 1.2 1996/08/13 22:58:15 jhill -// fdMgr.h => fdmanager.h -// -// Revision 1.1.1.1 1996/06/20 00:28:06 jhill -// ca server installation -// -// - -#ifndef includeCASOSDH -#define includeCASOSDH - - -#include -#include - -extern "C" { -// -// for htons() etc -// -# include - -// -// g++ 2.7.2 does not fix this file under sunos4 so I -// have provided the prototype elsewhere (in osiSock.h for now) -// -#if !(defined(SUNOS4) && defined(__GNUC__)) -# include -#endif -} // extern "C" - -#include -#include -#include - -class caServerI; - -class caServerOS; - -// -// casBeaconTimer -// -class casBeaconTimer : public osiTimer { -public: - casBeaconTimer (const osiTime &delay, caServerOS &osIn) : - osiTimer(delay), os (osIn) {} - void expire(); - const osiTime delay(); - osiBool again(); - const char *name() - { - return "casBeaconTimer"; - } -private: - caServerOS &os; - -}; - -class casServerReg; - -// -// caServerOS -// -class caServerOS { - friend class casServerReg; -public: - caServerOS (caServerI &casIn) : - cas (casIn), pRdReg (NULL), pBTmr (NULL) {} - caStatus init (); - ~caServerOS (); - - caStatus start (); - //caStatus process (const caTime &delay); - //caStatus installTimer (const caTime &delay, - // void (*pFunc)(void *pParam), void *pParam, - // caServerTimerId &id); - //caStatus deleteTimer (const caServerTimerId id); - - void recvCB (); - void sendCB () {}; // NOOP satifies template - - inline caServerI * operator -> (); - - int getFD(); -private: - caServerI &cas; - casServerReg *pRdReg; - casBeaconTimer *pBTmr; - -}; - -class casServerReg : public fdReg { -public: - casServerReg (caServerOS &osIn) : - os (osIn), fdReg (osIn.getFD(), fdrRead) {} - ~casServerReg (); -private: - caServerOS &os; - - void callBack (); -}; - -// no additions below this line -#endif // includeCASOSDH - diff --git a/src/cas/os/posix/casStreamOS.cc b/src/cas/os/posix/casStreamOS.cc deleted file mode 100644 index 24f733130..000000000 --- a/src/cas/os/posix/casStreamOS.cc +++ /dev/null @@ -1,456 +0,0 @@ -// -// casStreamOS.cc -// $Id$ -// -// -// $Log$ -// -// - -// -// CA server -// -#include -#include // casClient inline func - -class casStreamEvWakeup : public osiTimer { -public: - casStreamEvWakeup(casStreamOS &osIn) : - osiTimer(osiTime(0.0)), os(osIn) {} - ~casStreamEvWakeup() - { - os.pEvWk = NULL; - } - void expire(); - - void show(unsigned level); - - const char *name() - { - return "casStreamEvWakeup"; - } -private: - casStreamOS &os; -}; - -// -// casStreamEvWakeup::show() -// -void casStreamEvWakeup::show(unsigned level) -{ - printf ("casStreamEvWakeup at %x {\n", (unsigned) this); - this->osiTimer::show(level); - printf ("}\n"); -} - -// -// casStreamEvWakeup::expire() -// -void casStreamEvWakeup::expire() -{ - casProcCond cond; - cond = this->os.casEventSys::process(); - if (cond != casProcOk) { - // - // if "this" is being used above this - // routine on the stack then problems - // will result if we delete "this" here - // - // delete &this->os; - printf("strm event sys process failed\n"); - } -} - -// -// casStreamOS::ioBlockedSignal() -// -void casStreamOS::ioBlockedSignal() -{ - // - // in case there is something in the input buffer - // and currently nothing to be read from TCP - // - this->processInput(); - // - // in case recv is not armed, there is space in - // the input buffer, and there eventually will - // be something to read from TCP - // - this->armRecv(); -} - -// -// casStreamOS::eventSignal() -// -void casStreamOS::eventSignal() -{ - if (!this->pEvWk) { - this->pEvWk = new casStreamEvWakeup(*this); - if (!this->pEvWk) { - errMessage(S_cas_noMemory, - "casStreamOS::eventSignal()"); - } - } -} - -// -// casStreamOS::eventFlush() -// -void casStreamOS::eventFlush() -{ - this->armSend(); -} - - -// -// casStreamOS::casStreamOS() -// -casStreamOS::casStreamOS(caServerI &cas, casMsgIO &ioIn) : - casStrmClient(cas, ioIn) -{ - this->pRdReg = NULL; - this->pWtReg = NULL; - this->pEvWk = NULL; - this->sendBlocked = FALSE; -} - -// -// casStreamOS::init() -// -caStatus casStreamOS::init() -{ - caStatus status; - - // - // init the base classes - // - status = this->casStrmClient::init(); - if (status) { - return status; - } - this->setNonBlocking(); - - return S_cas_success; -} - - -// -// casStreamOS::~casStreamOS() -// -casStreamOS::~casStreamOS() -{ - // - // attempt to flush out any remaining messages - // - this->flush(); - - this->disarmSend(); - this->disarmRecv(); - - if (this->pEvWk) { - delete this->pEvWk; - } -} - -// -// casStreamOS::show() -// -void casStreamOS::show(unsigned level) -{ - this->casStrmClient::show(level); - printf("casStreamOS at %x\n", (unsigned) this); - printf("\tsendBlocked = %d\n", this->sendBlocked); - if (this->pWtReg) { - this->pWtReg->show(level); - } - if (this->pRdReg) { - this->pRdReg->show(level); - } - if (this->pEvWk) { - this->pEvWk->show(level); - } -} - - -// -// casClientStart () -// -caStatus casStreamOS::start() -{ - this->armRecv(); - return S_cas_success; -} - - -// -// casStreamOS::disarmRecv() -// -void casStreamOS::disarmRecv() -{ - if (this->pRdReg) { - delete this->pRdReg; -# if defined(DEBUG) - printf ("Read off %d\n", this->getFD()); - printf ("Recv backlog %u\n", - this->inBuf::bytesPresent()); - printf ("Send backlog %u\n", - this->outBuf::bytesPresent()); -# endif - } -} - - -// -// casStreamOS::armRecv () -// -void casStreamOS::armRecv() -{ - if (!this->pRdReg) { - if (this->inBuf::full()==aitTrue) { - return; - } - - this->pRdReg = new casStreamReadReg(*this); - if (!this->pRdReg) { - errMessage(S_cas_noMemory, "armRecv()"); - } - -# if defined(DEBUG) - printf ("Read on %d\n", this->getFD()); - printf ("Recv backlog %u\n", - this->inBuf::bytesPresent()); - printf ("Send backlog %u\n", - this->outBuf::bytesPresent()); -# endif - } -} - -// -// casStreamReadReg::show() -// -void casStreamReadReg::show(unsigned level) -{ - this->fdReg::show(level); - printf ("casStreamReadReg at %x\n", (unsigned) this); -} - -// -// casStreamReadReg::callBack () -// -void casStreamReadReg::callBack () -{ - casFillCondition fillCond; - casProcCond procCond; - - assert (this->os.pRdReg); - - // - // copy in new messages - // - fillCond = os.fill(); - procCond = os.processInput(); - if (fillCond == casFillDisconnect || - procCond == casProcDisconnect) { - delete &this->os; - } - else if (os.inBuf::full()==aitTrue) { - // - // If there isnt any space then temporarily - // stop calling this routine until problem is resolved - // either by: - // (1) sending or - // (2) a blocked IO op unblocks - // - delete this; - } - // - // NO CODE HERE - // (see deletes above) - // -} - - -// -// casStreamReadReg::~casStreamReadReg -// -casStreamReadReg::~casStreamReadReg () -{ - this->os.pRdReg = NULL; -} - - -// -// casStreamOS::sendBlockSignal() -// -void casStreamOS::sendBlockSignal() -{ - this->sendBlocked=TRUE; - this->armSend(); -} - - -// -// casStreamOS::armSend() -// -void casStreamOS::armSend() -{ - if (this->outBuf::bytesPresent()==0u) { - return; - } - - if (!this->pWtReg) { - this->pWtReg = new casStreamWriteReg(*this); - if (!this->pWtReg) { - errMessage(S_cas_noMemory, "armSend() failed"); - } - -# if defined(DEBUG) - printf ("Write on %d\n", this->getFD()); - printf ("Recv backlog %u\n", - this->inBuf::bytesPresent()); - printf ("Send backlog %u\n", - this->outBuf::bytesPresent()); -# endif - } -} - - -// -// casStreamOS::disarmSend() -// -void casStreamOS::disarmSend () -{ - if (this->pWtReg) { - delete this->pWtReg; -# if defined(DEBUG) - printf ("Write off %d\n", this->getFD()); - printf ("Recv backlog %u\n", - this->inBuf::bytesPresent()); - printf ("Send backlog %u\n", - this->outBuf::bytesPresent()); -# endif - } -} - - -// -// casStreamWriteReg::show() -// -void casStreamWriteReg::show(unsigned level) -{ - this->fdReg::show (level); - printf ("casStreamWriteReg at %x\n", (unsigned) this); -} - - -// -// casStreamWriteReg::callBack() -// -void casStreamWriteReg::callBack() -{ - casFlushCondition flushCond; - casProcCond procCond; - - assert (os.pWtReg); - - // - // attempt to flush the output buffer - // - flushCond = os.flush(); - switch (flushCond) { - case casFlushCompleted: - case casFlushPartial: - if (os.sendBlocked) { - os.sendBlocked = FALSE; - } - break; - case casFlushNone: - break; - case casFlushDisconnect: - return; - break; - default: - assert(0); - } - -# if defined(DEBUG) - printf ("write attempted on %d result was %d\n", - os.getFD(), flushCond); - printf ("Recv backlog %u\n", os.inBuf::bytesPresent()); - printf ("Send backlog %u\n", os.outBuf::bytesPresent()); -# endif - - // - // If we were able to send something then we need - // to process the input queue in case we were send - // blocked - // - procCond = this->os.processInput(); - if (procCond == casProcDisconnect) { - delete &this->os; - } - else { - // - // anything left in the send buffer that - // still needs to be sent ? - // (once this starts sending it doesnt stop until - // the outgoing buf is empty) - // - if (flushCond!=casFlushCompleted) { - casStreamOS *pStrmOS = &this->os; - // - // force the delete now so that the - // arm will work - // - delete this; - pStrmOS->armSend(); - } - } - // - // NO CODE HERE - // (see deletes above) - // -} - - -// -// casStreamWriteReg::~casStreamWriteReg () -// -casStreamWriteReg::~casStreamWriteReg() -{ - this->os.pWtReg = NULL; -} - -// -// casStreamOS::processInput() -// -casProcCond casStreamOS::processInput() -{ - caStatus status; - -# ifdef DEBUG - printf( - "Resp bytes to send=%d, Req bytes pending %d\n", - this->outBuf::bytesPresent(), - this->inBuf::bytesPresent()); -# endif - - status = this->processMsg(); - switch (status) { - case S_cas_sendBlocked: - case S_cas_partialMessage: - case S_cas_ioBlocked: - case S_cas_success: - if (this->inBuf::bytesAvailable()==0u) { - this->armSend (); - } - this->armRecv(); - return casProcOk; - break; - default: - errMessage (status, - "unexpected error processing client's input"); - return casProcDisconnect; - } -} - diff --git a/src/cas/os/posix/osiMutex.h b/src/cas/os/posix/osiMutex.h deleted file mode 100644 index eab6c23f9..000000000 --- a/src/cas/os/posix/osiMutex.h +++ /dev/null @@ -1,18 +0,0 @@ - -// -// osiMutex - OS independent mutex -// (NOOP on single threaded OS) -// -class osiMutex { -public: - // - // constructor that returns status - // (since g++ does not have exceptions) - // - int init() {return 0;} - void osiLock() {} - void osiUnlock() {} - void show (unsigned) {} -private: -}; - diff --git a/src/cas/os/vxWorks/README b/src/cas/os/vxWorks/README index 024556cac..c6ac03df8 100644 --- a/src/cas/os/vxWorks/README +++ b/src/cas/os/vxWorks/README @@ -1,5 +1,5 @@ -WORK IN PROGRESS +!! WORK IN PROGRESS - this code isnt yet thread safe !! this directory contains the vxWorks os dependent source for the EPICS ca server. This is a multi-threaded port of the diff --git a/src/cas/os/vxWorks/casClientOS.h b/src/cas/os/vxWorks/casClientOS.h index ec99fcc90..74efc41e0 100644 --- a/src/cas/os/vxWorks/casClientOS.h +++ b/src/cas/os/vxWorks/casClientOS.h @@ -18,9 +18,6 @@ public: casProcCond processInput(); caStatus start(); - void sendBlockSignal(); - void ioBlockedSignal(); - void eventSignal(); void eventFlush(); @@ -56,8 +53,6 @@ public: casProcCond processInput(); caStatus start(); - void sendBlockSignal() {} - void eventSignal(); void eventFlush(); diff --git a/src/cas/os/vxWorks/casOSD.h b/src/cas/os/vxWorks/casOSD.h index 2903b69d9..fe0b0642b 100644 --- a/src/cas/os/vxWorks/casOSD.h +++ b/src/cas/os/vxWorks/casOSD.h @@ -7,6 +7,9 @@ // Some BSD calls have crept in here // // $Log$ +// Revision 1.2 1996/09/16 18:27:10 jhill +// vxWorks port changes +// // Revision 1.1 1996/09/04 22:06:46 jhill // installed // @@ -19,18 +22,6 @@ #define includeCASOSDH -#include -#include - - -extern "C" { -// -// for htons() etc -// -# include -# include -} // extern "C" - #include #include @@ -78,15 +69,50 @@ public: caStatus init (); ~caServerOS (); - //caStatus start (); - inline caServerI * operator -> (); - //int getFD(); - private: caServerI &cas; casBeaconTimer *pBTmr; +}; + +// +// casDGIntfOS +// +class casDGIntfOS : public casDGIO { +public: + casDGIntfOS(casDGClient &client); + ~casDGIntfOS(); + + caStatus start(); + + void show(unsigned level) const; + + void recvCB(); + void sendCB(); +private: + casDGClient &client; + int tid; +}; + +// +// casIntfOS +// +class casIntfOS : public casIntfIO, public tsDLNode +{ +public: + casIntfOS (caServerI &casIn) : + cas (casIn), pRdReg (NULL) {} + caStatus init(const caAddr &addr, casDGClient &dgClientIn, + int autoBeaconAddr, int addConfigBeaconAddr); + ~casIntfOS(); + + void recvCB (); + void sendCB () {}; // NOOP satifies template + + casDGIO *newDGIO (casDGClient &dgClientIn) const; +private: + caServerI &cas; int tid; }; diff --git a/src/cas/os/vxWorks/casStreamOS.cc b/src/cas/os/vxWorks/casStreamOS.cc index 200147ef9..5ca86a39b 100644 --- a/src/cas/os/vxWorks/casStreamOS.cc +++ b/src/cas/os/vxWorks/casStreamOS.cc @@ -4,6 +4,9 @@ // // // $Log$ +// Revision 1.2 1996/09/16 18:27:11 jhill +// vxWorks port changes +// // Revision 1.1 1996/09/04 22:06:46 jhill // installed // @@ -21,14 +24,6 @@ #include // EPICS task priorities -// -// casStreamOS::ioBlockedSignal() -// -void casStreamOS::ioBlockedSignal() -{ - printf("in casStreamOS::ioBlockedSignal() ?\n"); -} - // // casStreamOS::eventSignal() // @@ -177,15 +172,6 @@ caStatus casStreamOS::start() return S_cas_success; } - -// -// casStreamOS::sendBlockSignal() -// -void casStreamOS::sendBlockSignal() -{ - printf("in casStreamOS::sendBlockSignal()\n"); -} - // // casStreamOS::processInput() // diff --git a/src/cas/os/vxWorks/osiMutex.h b/src/cas/os/vxWorks/osiMutex.h deleted file mode 100644 index f91bf81a5..000000000 --- a/src/cas/os/vxWorks/osiMutex.h +++ /dev/null @@ -1,113 +0,0 @@ - -// -// osiMutex - OS independent mutex -// (vxWorks version) -// -// -// NOTES: -// 1) epicsPrintf() is used in this file because we cant stand -// the logMsg() 8 arg API amd we dont want the messages from different -// tasks to co-mingle -// - -#include -#include -#include - - -#ifdef DEBUG_OSIMUTEX -#include -#endif - -#ifdef DEBUG_OSIMUTEX -#define osiLock() osiLockI (__FILE__, __LINE__) -#define osiUnlock() osiUnlockI (__FILE__, __LINE__) -#endif - -class osiMutex { -public: - osiMutex() - { - mutex = NULL; - } - // - // constructor that returns status - // (since g++ does not have exceptions) - // - int init () - { - this->mutex = semMCreate(SEM_Q_PRIORITY|SEM_INVERSION_SAFE); - if (this->mutex==NULL) - { - return -1; - } -# ifdef DEBUG_OSIMUTEX - epicsPrintf("created mutex at %lx\n", - (unsigned long) this->mutex); -# endif - return 0; - } - - ~osiMutex() - { - STATUS s; - s = semDelete (this->mutex); - assert (s==OK); -# ifdef DEBUG_OSIMUTEX - epicsPrintf("destroyed mutex at %lx\n", - (unsigned long) this->mutex); -# endif - } - -#ifdef DEBUG_OSIMUTEX - void osiLockI(const char *pFN, unsigned ln) -#else - void osiLock() -#endif - { - STATUS s; - if (!this->mutex) { - epicsPrintf( - "osiMutex: lock request before init was ignored\n"); - return; - } - assert(this->mutex); - s = semTake (this->mutex, WAIT_FOREVER); - assert (s==OK); -# ifdef DEBUG_OSIMUTEX - epicsPrintf("L%lx in %s at %u\n", - (unsigned long) this->mutex, - pFN, ln); -# endif - } - -#ifdef DEBUG_OSIMUTEX - void osiUnlockI(const char *pFN, unsigned ln) -#else - void osiUnlock() -#endif - { - STATUS s; - - if (!this->mutex) { - epicsPrintf( - "osiMutex: unlock request before init was ignored\n"); - return; - } - s = semGive (this->mutex); - assert (s==OK); -# ifdef DEBUG_OSIMUTEX - epicsPrintf("U%lx in %s at %d\n", - (unsigned long) this->mutex, - pFN, ln); -# endif - } - - void show(unsigned level) - { - semShow(this->mutex, (int) level); - } -private: - SEM_ID mutex; -}; -