many improvements

This commit is contained in:
Jeff Hill
1996-11-02 00:55:02 +00:00
parent 1f722b453d
commit 17ff2420b4
55 changed files with 2668 additions and 3369 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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";
}

View File

@@ -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();

View File

@@ -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";
}

View File

@@ -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;
};

View File

@@ -4,6 +4,7 @@
//
// main()
// (example single threaded ca server tool main loop)
//
int main (int argc, const char **argv)
{

View File

@@ -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

View File

@@ -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) */

View File

@@ -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 <server.h>
#include <caServerIIL.h> // caServerI in line func
#include <dbMapper.h> // ait to dbr types
#include <gddAppTable.h> // 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()
{
}

View File

@@ -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 <server.h>
#include <casCtxIL.h> // 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<casStrmClient> 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<casStrmClient> iterCl(this->clientList);
while ( (pClient = iterCl.next()) ) {
pClient->show(level);
}
this->dgClient.show(level);
casIntfOS *pIF;
tsDLFwdIter<casIntfOS> 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<casStrmClient> 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<casIntfOS> iter(this->intfList);
while ( (pIntf = iter.next()) ) {
pIntf->requestBeacon();
}
this->osiUnlock();
//
// double the period between beacons (but dont exceed max)
//
this->advanceBeaconPeriod();
}

View File

@@ -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<casRes>::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<casRes>::installItem(res);
}
//
// caServerI::removeItem()
//
inline casRes *caServerI::removeItem(casRes &res)
{
return this->uintResTable<casRes>::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

View File

@@ -29,14 +29,25 @@
*
* History
* $Log$
* Revision 1.1.1.1 1996/06/20 00:28:14 jhill
* ca server installation
*
*
*/
#include<server.h>
//
// 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()
{

View File

@@ -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 <server.h>
#include <casAsyncIOIIL.h> // casAsyncIOI inline func
#include <casChannelIIL.h> // casChannelI inline func
#include <casEventSysIL.h> // casEventSys inline func
#include <casEventSysIL.h> // casEventSys in line func
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
#include <casCtxIL.h> // 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);
}

View File

@@ -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

View File

@@ -29,11 +29,15 @@
*
* History
* $Log$
* Revision 1.1.1.1 1996/06/20 00:28:15 jhill
* ca server installation
*
*
*/
#include <server.h>
#include <casEventSysIL.h> // casEventSys in line func
//
// casChanDelEv()

View File

@@ -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 <casEventSysIL.h> // casEventSys inline func
#include <casAsyncIOIIL.h> // casAsyncIOI inline func
#include <casPVIIL.h> // casPVI inline func
#include <casCtxIL.h> // casCtx inline func
//
@@ -64,9 +68,7 @@ casChannelI::casChannelI(const casCtx &ctx, casChannel &chanAdapter) :
casChannelI::~casChannelI()
{
casAsyncIOI *pIO;
tsDLIter<casAsyncIOI> iterIO(this->ioInProgList);
casMonitor *pMonitor;
tsDLIter<casMonitor> iterMon(this->monitorList);
casChanDelEv *pCDEV;
caStatus status;
@@ -75,28 +77,29 @@ casChannelI::~casChannelI()
//
// cancel any pending asynchronous IO
//
pIO = iterIO();
tsDLFwdIter<casAsyncIOI> 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<casMonitor> 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<casAsyncIOI> 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<casMonitor> iter(this->monitorList);
this->lock();
while ( (pMon=iter()) ) {
tsDLFwdIter<casMonitor> 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<casMonitor> iter(this->monitorList);
this->lock();
tsDLFwdIter<casMonitor> 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);

View File

@@ -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 <casCoreClientIL.h>
//
// casChannelI::operator -> ()
//
@@ -75,10 +80,10 @@ inline void casChannelI::unlock()
inline void casChannelI::postEvent(const casEventMask &select, gdd &event)
{
casMonitor *pMon;
tsDLIter<casMonitor> iter(this->monitorList);
this->lock();
while ( (pMon = iter()) ) {
tsDLFwdIter<casMonitor> 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<casMonitor> iter(this->monitorList);
casMonitor *pMon;
while ( (pMon = iter()) ) {
this->lock();
tsDLFwdIter<casMonitor> iter(this->monitorList);
while ( (pMon = iter.next()) ) {
if ( clientIdIn == pMon->getClientId()) {
return pMon;
}
}
this->unlock();
return NULL;
}

View File

@@ -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 <server.h>
#include <casClientIL.h> // inline func for casClient
#include <casEventSysIL.h> // inline func for casEventSys
#include <casCtxIL.h> // inline func for casCtx
#include <inBufIL.h> // inline func for inBuf
#include <db_access.h>
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);

View File

@@ -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 <caServerIIL.h> // caServerI inline func
#include <casCtxIL.h> // 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

View File

@@ -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 <server.h>
#include <caServerIIL.h>
#include <caServerIIL.h> // caServerI in line func
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
#include <casEventSysIL.h> // casEventSys in line func
#include <casCtxIL.h> // casCtx in line func
#include <inBufIL.h> // inBuf in line func
#include <outBufIL.h> // 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<casAsyncIOI> iterIO(this->ioInProgList);
casAsyncIOI *pCurIO;
if (this->ctx.getServer()->getDebugLevel()>0u) {
@@ -111,18 +131,19 @@ casCoreClient::~casCoreClient()
}
this->osiLock();
tsDLFwdIter<casAsyncIOI> 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;
}

View File

@@ -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 <server.h>
#include <caServerIIL.h> // caServerI inline func
#include <casClientIL.h> // casClient inline func
#include <dgOutBufIL.h> // dgOutBuf inline func
#include <dgInBufIL.h> // dgInBuf inline func
#include <casCtxIL.h> // casCtx inline func
#include <inBufIL.h> // inBuf inline func
#include <outBufIL.h> // outBuf inline func
#include <casCoreClientIL.h> // casCoreClient inline func
#include <gddApps.h>
//
@@ -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;
}

View File

@@ -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 <stdio.h>
#include <limits.h>
#include <casdef.h>
#include <casEventMask.h>
#include <server.h>
#ifdef TEST
main ()
@@ -86,6 +88,23 @@ main ()
}
#endif
//
// casEventRegistry::init()
//
int casEventRegistry::init()
{
if (!this->hasBeenInitialized) {
int status;
status = this->resTable <casEventMaskEntry, stringId>::
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->allocator<CHAR_BIT*sizeof(evMask.mask)) {
evMask.mask = 1u<<(this->allocator++);
}
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 &reg, 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 <casEventMaskEntry, stringId>::show(level);
this->mutex.osiUnlock();
}

View File

@@ -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 <resourceLib.h>
#include "resourceLib.h"
class casEventMaskEntry;
@@ -97,38 +100,6 @@ public:
private:
};
class casEventRegistry : resTable <casEventMaskEntry, stringId> {
public:
casEventRegistry() : allocator(0)
{
int status;
status = this->resTable <casEventMaskEntry, stringId>::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 &reg, const char *pName)
{
*this = reg.registerEvent (pName);
}
inline casEventMask operator| (const casEventMask &lhs, const casEventMask &rhs)
{
casEventMask result;

View File

@@ -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 <server.h>
#include <casEventSysIL.h> // casMonitor inline func
#if 0
VERSIONID(caEventQueuec,"%W% %G%")
#endif
#if 0
#include <memDebugLib.h>
#endif
//
// casEventSys::show()
//
void casEventSys::show(unsigned level)
void casEventSys::show(unsigned level) const
{
printf ("casEventSys at %x\n", (unsigned) this);
if (level>=1u) {

View File

@@ -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()
//

View File

@@ -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 <tsDLList.h>
#include <resourceLib.h>
#include <caProto.h>
#include "tsDLList.h"
#include "resourceLib.h"
#include "caProto.h"
typedef aitUint32 caResId;
@@ -67,7 +70,7 @@ class casChannelI;
//
class casEvent : public tsDLNode<casEvent> {
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<casRes>
{
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<ioBlocked> {
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<ioBlocked> {
friend class ioBlocked;
class ioBlockedList : private tsDLList<ioBlocked> {
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<ioBlocked> 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<casAsyncIOI> {
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<casMonitor> monitorList;
tsDLList<casAsyncIOI> 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;
}

View File

@@ -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 <server.h>
#include <casEventSysIL.h>
//
// 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 <casEventSysIL.h> // casEventSys in line func
#include <casMonEventIL.h> // casMonEvent in line func
#include <casCtxIL.h> // casCtx in line func
//
// casMonEvent::cbFunc()

View File

@@ -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

View File

@@ -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 <casChannelIIL.h> // casChannelI inline func
#include <casEventSysIL.h> // casEventSys inline func
#include <casMonEventIL.h> // casMonEvent inline func
#include <casCtxIL.h> // casCtx inline func
//

View File

@@ -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<server.h>
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
}

View File

@@ -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 <server.h>
#include <casPVIIL.h> // casPVI inline func
#include <casCtxIL.h> // casCtx inline func
casPV::casPV (const casCtx &ctx, const char * const pPVName) :
casPVI (*ctx.getServer(), pPVName, *this)

View File

@@ -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 <server.h>
#include <casPVIIL.h> // casPVI inline func
#include <caServerIIL.h> // 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<casPVListChan> iter(this->chanList);
this->lock();
//
// delete any attached channels
//
pChan = iter();
tsDLFwdIter<casPVListChan> 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);
}

View File

@@ -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 <dbMapper.h>
#include "dbMapper.h"
//
@@ -219,10 +222,12 @@ inline void casPVI::postEvent (const casEventMask &select, gdd &event)
//
event.markConstant();
tsDLIter<casPVListChan> iter(this->chanList);
while ( (pChan = iter()) ) {
this->lock();
tsDLFwdIter<casPVListChan> iter(this->chanList);
while ( (pChan = iter.next()) ) {
pChan->postEvent(select, event);
}
this->unlock();
}
#endif // casPVIIL_h

View File

@@ -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 <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 <gddApps.h>
#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<casChannelI> 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<casChannelI> 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<casChannelI> iter(this->chanList);
unsigned size;
char *pMalloc;
@@ -827,7 +828,8 @@ caStatus casStrmClient::hostNameAction()
}
this->pHostName = pMalloc;
while ( (pciu = iter()) ) {
tsDLFwdIter<casChannelI> 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<casChannelI> 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<casChannelI> 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<casChannelI> 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<casChannelI> 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<casChannelI> 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();
}

View File

@@ -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 <alarm.h> // EPICS alarm severity/condition
#include <errMdef.h> // EPICS error codes
#include <gdd.h> // 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 <casEventMask.h> // EPICS event select class
#include <casInternal.h> // 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)

View File

@@ -29,42 +29,18 @@
*
* History
* $Log$
* Revision 1.1.1.1 1996/06/20 00:28:15 jhill
* ca server installation
*
*
*/
#include<server.h>
//
// 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;
}

View File

@@ -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<server.h>
#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");
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <ctype.h>
#include <server.h>
#include <sigPipeIgnore.h>
#ifdef SOLARIS
# include <sys/filio.h>
#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;
}

View File

@@ -28,377 +28,22 @@
* History
*/
//
//
// Should I fetch the MTU from the outgoing interface?
//
//
#include <server.h>
#ifdef SOLARIS
# include <sys/filio.h>
#endif
#include <dgInBufIL.h> // 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;
}

View File

@@ -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 <osiSock.h>
// ca
#include <addrList.h>
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

View File

@@ -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 <server.h>
#ifdef SOLARIS
# include <sys/filio.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
//
// the SUNOS4 and vxWorks5.2 prototypes are trad C
//
#if !defined(SUNOS4) && !defined(vxWorks)
#include <arpa/inet.h>
#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()
//

View File

@@ -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 <server.h>
#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();
}

View File

@@ -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 ();
};

View File

@@ -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 <server.h>
#include <casClientIL.h> // 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);
}

View File

@@ -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 <unistd.h>
#include <errno.h>
extern "C" {
//
// for htons() etc
//
# include <netinet/in.h>
//
// 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 <netdb.h>
#endif
} // extern "C"
#include <osiMutex.h>
#include <osiTimer.h>
#include <fdManager.h>
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

View File

@@ -1,456 +0,0 @@
//
// casStreamOS.cc
// $Id$
//
//
// $Log$
//
//
//
// CA server
//
#include<server.h>
#include <casClientIL.h> // 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;
}
}

View File

@@ -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:
};

View File

@@ -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

View File

@@ -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();

View File

@@ -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 <unistd.h>
#include <errno.h>
extern "C" {
//
// for htons() etc
//
# include <netinet/in.h>
# include <ioLib.h>
} // extern "C"
#include <osiMutex.h>
#include <osiTimer.h>
@@ -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<casIntfOS>
{
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;
};

View File

@@ -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 <task_params.h> // 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()
//

View File

@@ -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 <semLib.h>
#include <epicsAssert.h>
#include <epicsPrint.h>
#ifdef DEBUG_OSIMUTEX
#include <stdio.h>
#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;
};