many improvements
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
//
|
||||
// main()
|
||||
// (example single threaded ca server tool main loop)
|
||||
//
|
||||
int main (int argc, const char **argv)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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) */
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ®, 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ®, const char *pName)
|
||||
{
|
||||
*this = reg.registerEvent (pName);
|
||||
}
|
||||
|
||||
inline casEventMask operator| (const casEventMask &lhs, const casEventMask &rhs)
|
||||
{
|
||||
casEventMask result;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
//
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
//
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 ();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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()
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user