improved structure and thread safety
This commit is contained in:
@@ -25,7 +25,6 @@ SRC_DIRS += $(CA)
|
||||
|
||||
INC += casdef.h
|
||||
INC += casEventMask.h
|
||||
INC += casInternal.h
|
||||
INC += caNetAddr.h
|
||||
|
||||
LIBSRCS += caServer.cc
|
||||
@@ -38,13 +37,15 @@ LIBSRCS += casPV.cc
|
||||
LIBSRCS += casPVI.cc
|
||||
LIBSRCS += casChannel.cc
|
||||
LIBSRCS += casChannelI.cc
|
||||
LIBSRCS += casPVListChan.cc
|
||||
LIBSRCS += casChanDelEv.cc
|
||||
LIBSRCS += casAsyncIOI.cc
|
||||
LIBSRCS += casAsyncReadIO.cc
|
||||
LIBSRCS += casAsyncReadIOI.cc
|
||||
LIBSRCS += casAsyncWriteIO.cc
|
||||
LIBSRCS += casAsyncWriteIOI.cc
|
||||
LIBSRCS += casAsyncPVExistIO.cc
|
||||
LIBSRCS += casAsyncPVExistIOI.cc
|
||||
LIBSRCS += casAsyncPVAttachIO.cc
|
||||
LIBSRCS += casAsyncPVAttachIOI.cc
|
||||
LIBSRCS += casEventSys.cc
|
||||
LIBSRCS += casMonitor.cc
|
||||
LIBSRCS += casMonEvent.cc
|
||||
@@ -60,8 +61,8 @@ LIBSRCS += caNetAddr.cc
|
||||
LIBSRCS += beaconTimer.cc
|
||||
LIBSRCS += beaconAnomalyGovernor.cc
|
||||
LIBSRCS += clientBufMemoryManager.cpp
|
||||
LIBSRCS += chanIntfForPV.cc
|
||||
|
||||
LIBSRCS += caServerOS.cc
|
||||
LIBSRCS += casIntfOS.cc
|
||||
LIBSRCS += casDGIntfOS.cc
|
||||
LIBSRCS += casStreamOS.cc
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// Example EPICS CA directory server
|
||||
// Example EPICS CA directory server
|
||||
//
|
||||
//
|
||||
// caServer
|
||||
// |
|
||||
// directoryServer
|
||||
// caServer
|
||||
// |
|
||||
// directoryServer
|
||||
//
|
||||
//
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#define caNetAddrSock
|
||||
#include "casdef.h"
|
||||
#include "epicsAssert.h"
|
||||
@@ -34,7 +35,7 @@
|
||||
|
||||
|
||||
#ifndef NELEMENTS
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
#endif
|
||||
|
||||
class directoryServer;
|
||||
@@ -44,24 +45,24 @@ class directoryServer;
|
||||
//
|
||||
class pvInfo {
|
||||
public:
|
||||
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
|
||||
addr(addrIn), pNext(pvInfo::pFirst)
|
||||
{
|
||||
pvInfo::pFirst = this;
|
||||
this->pName = new char [strlen(pNameIn)+1u];
|
||||
assert(this->pName);
|
||||
strcpy(this->pName, pNameIn);
|
||||
}
|
||||
|
||||
const struct sockaddr_in getAddr() const { return this->addr; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const pvInfo *getNext () const { return this->pNext; }
|
||||
static const pvInfo *getFirst () { return pvInfo::pFirst; }
|
||||
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
|
||||
addr(addrIn), pNext(pvInfo::pFirst)
|
||||
{
|
||||
pvInfo::pFirst = this;
|
||||
this->pName = new char [strlen(pNameIn)+1u];
|
||||
assert(this->pName);
|
||||
strcpy(this->pName, pNameIn);
|
||||
}
|
||||
|
||||
const struct sockaddr_in getAddr() const { return this->addr; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const pvInfo *getNext () const { return this->pNext; }
|
||||
static const pvInfo *getFirst () { return pvInfo::pFirst; }
|
||||
private:
|
||||
struct sockaddr_in addr;
|
||||
char *pName;
|
||||
const pvInfo *pNext;
|
||||
static const pvInfo *pFirst;
|
||||
struct sockaddr_in addr;
|
||||
char * pName;
|
||||
const pvInfo * pNext;
|
||||
static const pvInfo * pFirst;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -77,41 +78,39 @@ private:
|
||||
class pvEntry // X aCC 655
|
||||
: public stringId, public tsSLNode<pvEntry> {
|
||||
public:
|
||||
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
|
||||
inline ~pvEntry();
|
||||
inline ~pvEntry();
|
||||
|
||||
const pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
const pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
|
||||
private:
|
||||
const pvInfo &info;
|
||||
directoryServer &cas;
|
||||
const pvInfo &info;
|
||||
directoryServer &cas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// directoryServer
|
||||
//
|
||||
class directoryServer : public caServer {
|
||||
public:
|
||||
directoryServer (const char * const pvPrefix, unsigned aliasCount);
|
||||
~directoryServer();
|
||||
void show (unsigned level) const;
|
||||
pvExistReturn pvExistTest (const casCtx&, const char *pPVName);
|
||||
directoryServer ( const char * const pvPrefix, unsigned aliasCount );
|
||||
~directoryServer();
|
||||
void show ( unsigned level ) const;
|
||||
pvExistReturn pvExistTest ( const casCtx&, const char *pPVName );
|
||||
|
||||
void installAliasName (const pvInfo &info, const char *pAliasName);
|
||||
inline void removeAliasName(pvEntry &entry);
|
||||
void installAliasName ( const pvInfo &info, const char *pAliasName );
|
||||
inline void removeAliasName ( pvEntry &entry );
|
||||
|
||||
private:
|
||||
resTable<pvEntry,stringId> stringResTbl;
|
||||
resTable < pvEntry, stringId > stringResTbl;
|
||||
};
|
||||
|
||||
|
||||
@@ -120,9 +119,9 @@ private:
|
||||
//
|
||||
inline void directoryServer::removeAliasName(pvEntry &entry)
|
||||
{
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -130,7 +129,7 @@ inline void directoryServer::removeAliasName(pvEntry &entry)
|
||||
//
|
||||
inline pvEntry::~pvEntry()
|
||||
{
|
||||
this->cas.removeAliasName(*this);
|
||||
this->cas.removeAliasName(*this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -138,9 +137,9 @@ inline pvEntry::~pvEntry()
|
||||
//
|
||||
inline void pvEntry::destroy ()
|
||||
{
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
#include "directoryServer.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
LOCAL int parseDirectoryFile (const char *pFileName);
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName);
|
||||
static int parseDirectoryFile (const char *pFileName);
|
||||
static int parseDirectoryFP (FILE *pf, const char *pFileName);
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE (~0ul)
|
||||
@@ -109,7 +107,7 @@ extern int main (int argc, const char **argv)
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFile (const char *pFileName)
|
||||
static int parseDirectoryFile (const char *pFileName)
|
||||
{
|
||||
|
||||
FILE *pf;
|
||||
@@ -139,7 +137,7 @@ LOCAL int parseDirectoryFile (const char *pFileName)
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
static int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
{
|
||||
pvInfo *pPVI;
|
||||
char pvNameStr[128];
|
||||
@@ -193,8 +191,8 @@ LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
ipa.sin_port = 0u; // use the default CA server port
|
||||
}
|
||||
|
||||
pPVI = new pvInfo (pvNameStr, ipa);
|
||||
if (!pPVI) {
|
||||
pPVI = new pvInfo ( pvNameStr, ipa );
|
||||
if ( ! pPVI ) {
|
||||
fprintf (stderr, "Unable to allocate space for a new PV in \"%s\" with PV=\"%s\" host=\"%s\"\n",
|
||||
pFileName, pvNameStr, hostNameStr);
|
||||
return -1;
|
||||
|
||||
@@ -29,7 +29,7 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncReadIO ( ctx, *this, valueIn );
|
||||
pIO = new exAsyncReadIO ( this->cas, ctx, *this, valueIn );
|
||||
if (!pIO) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncWriteIO ( ctx, *this, valueIn );
|
||||
pIO = new exAsyncWriteIO ( this->cas, ctx, *this, valueIn );
|
||||
if ( ! pIO ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -62,10 +62,10 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
|
||||
//
|
||||
// exAsyncWriteIO::exAsyncWriteIO()
|
||||
//
|
||||
exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
const gdd &valueIn ) :
|
||||
exAsyncWriteIO::exAsyncWriteIO ( exServer & cas,
|
||||
const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ) :
|
||||
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( pvIn.getCAS()->createTimer () ), pValue(valueIn)
|
||||
timer ( cas.createTimer () ), pValue(valueIn)
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
@@ -76,9 +76,7 @@ exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
exAsyncWriteIO::~exAsyncWriteIO()
|
||||
{
|
||||
this->pv.removeIO();
|
||||
if ( this->pv.getCAS() ) {
|
||||
this->timer.destroy ();
|
||||
}
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -88,7 +86,7 @@ exAsyncWriteIO::~exAsyncWriteIO()
|
||||
epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
caStatus status;
|
||||
status = this->pv.update ( this->pValue );
|
||||
status = this->pv.update ( *this->pValue );
|
||||
this->postIOCompletion ( status );
|
||||
return noRestart;
|
||||
}
|
||||
@@ -96,10 +94,10 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* cur
|
||||
//
|
||||
// exAsyncReadIO::exAsyncReadIO()
|
||||
//
|
||||
exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
gdd &protoIn ) :
|
||||
exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
|
||||
exAsyncPV & pvIn, gdd & protoIn ) :
|
||||
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( pvIn.getCAS()->createTimer() ), pProto ( protoIn )
|
||||
timer ( cas.createTimer() ), pProto ( protoIn )
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
@@ -110,9 +108,7 @@ exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
exAsyncReadIO::~exAsyncReadIO()
|
||||
{
|
||||
this->pv.removeIO ();
|
||||
if ( this->pv.getCAS() ) {
|
||||
this->timer.destroy ();
|
||||
}
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,8 +30,10 @@ class exFixedStringDestructor: public gddDestructor {
|
||||
//
|
||||
// exPV::exPV()
|
||||
//
|
||||
exPV::exPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
timer ( this->getCAS()->createTimer() ),
|
||||
exPV::exPV ( exServer & casIn, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
cas ( casIn ),
|
||||
timer ( cas.createTimer() ),
|
||||
info ( setup ),
|
||||
interest ( false ),
|
||||
preCreate ( preCreateFlag ),
|
||||
@@ -77,17 +79,14 @@ void exPV::destroy()
|
||||
//
|
||||
// exPV::update()
|
||||
//
|
||||
caStatus exPV::update(smartConstGDDPointer pValueIn)
|
||||
caStatus exPV::update ( const gdd & valueIn )
|
||||
{
|
||||
caServer *pCAS = this->getCAS();
|
||||
caStatus cas;
|
||||
|
||||
# if DEBUG
|
||||
printf("Setting %s too:\n", this->info.getName().string());
|
||||
valueIn.dump();
|
||||
# endif
|
||||
|
||||
cas = this->updateValue (pValueIn);
|
||||
caStatus cas = this->updateValue ( valueIn );
|
||||
if ( cas || ( ! this->pValue.valid() ) ) {
|
||||
return cas;
|
||||
}
|
||||
@@ -95,9 +94,10 @@ caStatus exPV::update(smartConstGDDPointer pValueIn)
|
||||
//
|
||||
// post a value change event
|
||||
//
|
||||
if (this->interest==true && pCAS!=NULL) {
|
||||
casEventMask select(pCAS->valueEventMask()|pCAS->logEventMask());
|
||||
this->postEvent (select, *this->pValue);
|
||||
caServer * pCAS = this->getCAS();
|
||||
if ( this->interest == true && pCAS != NULL ) {
|
||||
casEventMask select ( pCAS->valueEventMask() | pCAS->logEventMask() );
|
||||
this->postEvent ( select, valueIn );
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
@@ -129,16 +129,13 @@ aitEnum exPV::bestExternalType () const
|
||||
//
|
||||
// exPV::interestRegister()
|
||||
//
|
||||
caStatus exPV::interestRegister()
|
||||
caStatus exPV::interestRegister ()
|
||||
{
|
||||
caServer *pCAS = this->getCAS();
|
||||
|
||||
if ( ! pCAS ) {
|
||||
if ( ! this->getCAS() ) {
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
this->interest = true;
|
||||
|
||||
if ( this->scanOn && this->getScanPeriod() > 0.0 &&
|
||||
this->getScanPeriod() < this->timer.getExpireDelay() ) {
|
||||
this->timer.start ( *this, this->getScanPeriod() );
|
||||
@@ -174,7 +171,7 @@ void exPV::show ( unsigned level ) const
|
||||
//
|
||||
// exPV::initFT()
|
||||
//
|
||||
void exPV::initFT()
|
||||
void exPV::initFT ()
|
||||
{
|
||||
if ( exPV::hasBeenInitialized ) {
|
||||
return;
|
||||
@@ -203,7 +200,7 @@ void exPV::initFT()
|
||||
//
|
||||
// exPV::getPrecision()
|
||||
//
|
||||
caStatus exPV::getPrecision(gdd &prec)
|
||||
caStatus exPV::getPrecision ( gdd & prec )
|
||||
{
|
||||
prec.put(4u);
|
||||
return S_cas_success;
|
||||
@@ -212,7 +209,7 @@ caStatus exPV::getPrecision(gdd &prec)
|
||||
//
|
||||
// exPV::getHighLimit()
|
||||
//
|
||||
caStatus exPV::getHighLimit(gdd &value)
|
||||
caStatus exPV::getHighLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getHopr());
|
||||
return S_cas_success;
|
||||
@@ -221,7 +218,7 @@ caStatus exPV::getHighLimit(gdd &value)
|
||||
//
|
||||
// exPV::getLowLimit()
|
||||
//
|
||||
caStatus exPV::getLowLimit(gdd &value)
|
||||
caStatus exPV::getLowLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getLopr());
|
||||
return S_cas_success;
|
||||
@@ -230,7 +227,7 @@ caStatus exPV::getLowLimit(gdd &value)
|
||||
//
|
||||
// exPV::getUnits()
|
||||
//
|
||||
caStatus exPV::getUnits(gdd &units)
|
||||
caStatus exPV::getUnits( gdd & units )
|
||||
{
|
||||
aitString str("furlongs", aitStrRefConstImortal);
|
||||
units.put(str);
|
||||
@@ -283,7 +280,7 @@ caStatus exPV::getEnums ( gdd & enumsIn )
|
||||
//
|
||||
// exPV::getValue()
|
||||
//
|
||||
caStatus exPV::getValue(gdd &value)
|
||||
caStatus exPV::getValue ( gdd & value )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
@@ -309,18 +306,18 @@ caStatus exPV::getValue(gdd &value)
|
||||
// exPV::write()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::write (const casCtx &, const gdd &valueIn)
|
||||
caStatus exPV::write ( const casCtx &, const gdd & valueIn )
|
||||
{
|
||||
return this->update (valueIn);
|
||||
return this->update ( valueIn );
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::read()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::read (const casCtx &, gdd &protoIn)
|
||||
caStatus exPV::read ( const casCtx &, gdd & protoIn )
|
||||
{
|
||||
return this->ft.read (*this, protoIn);
|
||||
return this->ft.read ( *this, protoIn );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -328,11 +325,11 @@ caStatus exPV::read (const casCtx &, gdd &protoIn)
|
||||
//
|
||||
// for access control - optional
|
||||
//
|
||||
casChannel *exPV::createChannel (const casCtx &ctx,
|
||||
casChannel *exPV::createChannel ( const casCtx &ctx,
|
||||
const char * const /* pUserName */,
|
||||
const char * const /* pHostName */)
|
||||
const char * const /* pHostName */ )
|
||||
{
|
||||
return new exChannel (ctx);
|
||||
return new exChannel ( ctx );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -340,7 +337,7 @@ casChannel *exPV::createChannel (const casCtx &ctx,
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exFixedStringDestructor::run (void *pUntyped)
|
||||
void exFixedStringDestructor::run ( void * pUntyped )
|
||||
{
|
||||
aitFixedString *ps = (aitFixedString *) pUntyped;
|
||||
delete [] ps;
|
||||
|
||||
@@ -49,9 +49,9 @@ void exScalarPV::scan()
|
||||
// throughput under sunos4 because gettimeofday() is
|
||||
// slow)
|
||||
//
|
||||
this->currentTime = epicsTime::getCurrent();
|
||||
this->currentTime = epicsTime::getCurrent ();
|
||||
|
||||
pDD = new gddScalar (gddAppType_value, aitEnumFloat64);
|
||||
pDD = new gddScalar ( gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
@@ -59,27 +59,27 @@ void exScalarPV::scan()
|
||||
//
|
||||
// smart pointer class manages reference count after this point
|
||||
//
|
||||
gddStatus = pDD->unreference();
|
||||
assert (!gddStatus);
|
||||
gddStatus = pDD->unreference ();
|
||||
assert ( ! gddStatus );
|
||||
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
radians = ( rand () * 2.0 * myPI ) / RAND_MAX;
|
||||
if ( this->pValue.valid () ) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = tsMin (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = tsMax (newValue, limit);
|
||||
newValue += (float) ( sin (radians) / 10.0 );
|
||||
limit = (float) this->info.getHopr ();
|
||||
newValue = tsMin ( newValue, limit );
|
||||
limit = (float) this->info.getLopr ();
|
||||
newValue = tsMax ( newValue, limit );
|
||||
*pDD = newValue;
|
||||
aitTimeStamp gddts = this->currentTime;
|
||||
pDD->setTimeStamp (&gddts);
|
||||
status = this->update (pDD);
|
||||
pDD->setTimeStamp ( & gddts );
|
||||
status = this->update ( *pDD );
|
||||
if (status!=S_casApp_success) {
|
||||
errMessage (status, "scalar scan update failed\n");
|
||||
errMessage ( status, "scalar scan update failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,21 +95,25 @@ void exScalarPV::scan()
|
||||
// result in each value change events retaining an
|
||||
// independent value on the event queue.
|
||||
//
|
||||
caStatus exScalarPV::updateValue (smartConstGDDPointer pValueIn)
|
||||
caStatus exScalarPV::updateValue ( const gdd & valueIn )
|
||||
{
|
||||
if ( ! pValueIn.valid () ) {
|
||||
return S_casApp_undefined;
|
||||
}
|
||||
|
||||
//
|
||||
// Really no need to perform this check since the
|
||||
// server lib verifies that all requests are in range
|
||||
//
|
||||
if (!pValueIn->isScalar()) {
|
||||
if ( ! valueIn.isScalar() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
this->pValue = pValueIn;
|
||||
if ( ! pValue.valid () ) {
|
||||
this->pValue = new gddScalar (
|
||||
gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pValue.valid () ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
|
||||
this->pValue->put ( & valueIn );
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -44,9 +44,10 @@ pvInfo exServer::bloaty (-1.0, "bloaty", 10.0f, -10.0f, aitEnumFloat64, excasIoS
|
||||
// exServer::exServer()
|
||||
//
|
||||
exServer::exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOnIn ) :
|
||||
simultAsychIOCount (0u),
|
||||
scanOn (scanOnIn)
|
||||
unsigned aliasCount, bool scanOnIn,
|
||||
bool asyncScan ) :
|
||||
pTimerQueue ( 0 ), simultAsychIOCount ( 0u ),
|
||||
scanOn ( scanOnIn )
|
||||
{
|
||||
unsigned i;
|
||||
exPV *pPV;
|
||||
@@ -58,6 +59,16 @@ exServer::exServer ( const char * const pvPrefix,
|
||||
|
||||
exPV::initFT();
|
||||
|
||||
if ( asyncScan ) {
|
||||
unsigned timerPriotity;
|
||||
epicsThreadBooleanStatus etbs = epicsThreadLowestPriorityLevelAbove (
|
||||
epicsThreadGetPrioritySelf (), & timerPriotity );
|
||||
if ( etbs != epicsThreadBooleanStatusSuccess ) {
|
||||
timerPriotity = epicsThreadGetPrioritySelf ();
|
||||
}
|
||||
this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, timerPriotity );
|
||||
}
|
||||
|
||||
//
|
||||
// pre-create all of the simple PVs that this server will export
|
||||
//
|
||||
@@ -236,10 +247,31 @@ pvAttachReturn exServer::pvAttach // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::setDebugLevel ()
|
||||
//
|
||||
void exServer::setDebugLevel ( unsigned level )
|
||||
{
|
||||
this->caServer::setDebugLevel ( level );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::createTimer ()
|
||||
//
|
||||
class epicsTimer & exServer::createTimer ()
|
||||
{
|
||||
if ( this->pTimerQueue ) {
|
||||
return this->pTimerQueue->createTimer ();
|
||||
}
|
||||
else {
|
||||
return this->caServer::createTimer ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// pvInfo::createPV()
|
||||
//
|
||||
exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
exPV *pvInfo::createPV ( exServer & cas,
|
||||
bool preCreateFlag, bool scanOn )
|
||||
{
|
||||
if (this->pPV) {
|
||||
@@ -256,10 +288,10 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
if (this->elementCount==1u) {
|
||||
switch (this->ioType){
|
||||
case excasIoSync:
|
||||
pNewPV = new exScalarPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
case excasIoAsync:
|
||||
pNewPV = new exAsyncPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exAsyncPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
default:
|
||||
pNewPV = NULL;
|
||||
@@ -268,7 +300,7 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
}
|
||||
else {
|
||||
if ( this->ioType == excasIoSync ) {
|
||||
pNewPV = new exVectorPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exVectorPV ( cas, *this, preCreateFlag, scanOn );
|
||||
}
|
||||
else {
|
||||
pNewPV = NULL;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "gddAppFuncTable.h"
|
||||
#include "epicsTimer.h"
|
||||
#include "casdef.h"
|
||||
@@ -124,7 +125,8 @@ private:
|
||||
class exPV : public casPV, public epicsTimerNotify,
|
||||
public tsSLNode < exPV > {
|
||||
public:
|
||||
exPV ( pvInfo & setup, bool preCreateFlag, bool scanOn );
|
||||
exPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOn );
|
||||
virtual ~exPV();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
@@ -158,7 +160,7 @@ public:
|
||||
//
|
||||
// This gets called when the pv gets a new value
|
||||
//
|
||||
caStatus update ( smartConstGDDPointer pValue );
|
||||
caStatus update ( const gdd & );
|
||||
|
||||
//
|
||||
// Gets called when we add noise to the current value
|
||||
@@ -190,7 +192,8 @@ public:
|
||||
const char * const pHostName );
|
||||
|
||||
protected:
|
||||
smartConstGDDPointer pValue;
|
||||
smartGDDPointer pValue;
|
||||
exServer & cas;
|
||||
epicsTimer & timer;
|
||||
pvInfo & info;
|
||||
bool interest;
|
||||
@@ -198,7 +201,7 @@ protected:
|
||||
bool scanOn;
|
||||
static epicsTime currentTime;
|
||||
|
||||
virtual caStatus updateValue ( smartConstGDDPointer pValue ) = 0;
|
||||
virtual caStatus updateValue ( const gdd & ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
@@ -229,11 +232,13 @@ private:
|
||||
//
|
||||
class exScalarPV : public exPV {
|
||||
public:
|
||||
exScalarPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( setup, preCreateFlag, scanOnIn) {}
|
||||
exScalarPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
private:
|
||||
caStatus updateValue (smartConstGDDPointer pValue);
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
@@ -241,36 +246,45 @@ private:
|
||||
//
|
||||
class exVectorPV : public exPV {
|
||||
public:
|
||||
exVectorPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( setup, preCreateFlag, scanOnIn) {}
|
||||
exVectorPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
|
||||
unsigned maxDimension() const;
|
||||
aitIndex maxBound (unsigned dimension) const;
|
||||
|
||||
private:
|
||||
caStatus updateValue (smartConstGDDPointer pValue);
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
// exServer
|
||||
//
|
||||
class exServer : public caServer {
|
||||
class exServer : private caServer {
|
||||
public:
|
||||
exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOn );
|
||||
unsigned aliasCount, bool scanOn,
|
||||
bool asyncScan );
|
||||
~exServer ();
|
||||
void show ( unsigned level ) const;
|
||||
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
|
||||
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
|
||||
void installAliasName ( pvInfo & info, const char * pAliasName );
|
||||
inline void removeAliasName ( pvEntry & entry );
|
||||
void removeIO();
|
||||
void removeIO ();
|
||||
void removeAliasName ( pvEntry & entry );
|
||||
|
||||
class epicsTimer & createTimer ();
|
||||
void setDebugLevel ( unsigned level );
|
||||
|
||||
private:
|
||||
resTable < pvEntry, stringId > stringResTbl;
|
||||
epicsTimerQueueActive * pTimerQueue;
|
||||
unsigned simultAsychIOCount;
|
||||
bool scanOn;
|
||||
|
||||
void installAliasName ( pvInfo & info, const char * pAliasName );
|
||||
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
|
||||
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
|
||||
|
||||
//
|
||||
// list of pre-created PVs
|
||||
//
|
||||
@@ -292,7 +306,8 @@ private:
|
||||
//
|
||||
class exAsyncPV : public exScalarPV {
|
||||
public:
|
||||
exAsyncPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn );
|
||||
exAsyncPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn );
|
||||
caStatus read ( const casCtx & ctxIn, gdd & protoIn );
|
||||
caStatus write ( const casCtx & ctxIn, const gdd & value );
|
||||
void removeIO();
|
||||
@@ -318,7 +333,7 @@ private:
|
||||
//
|
||||
class exAsyncWriteIO : public casAsyncWriteIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncWriteIO ( const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn );
|
||||
exAsyncWriteIO ( exServer &, const casCtx & ctxIn, exAsyncPV &, const gdd & );
|
||||
~exAsyncWriteIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
@@ -332,7 +347,7 @@ private:
|
||||
//
|
||||
class exAsyncReadIO : public casAsyncReadIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncReadIO ( const casCtx & ctxIn, exAsyncPV & pvIn, gdd & protoIn );
|
||||
exAsyncReadIO ( exServer &, const casCtx &, exAsyncPV &, gdd & );
|
||||
virtual ~exAsyncReadIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
@@ -519,9 +534,9 @@ inline void exServer::removeIO()
|
||||
}
|
||||
}
|
||||
|
||||
inline exAsyncPV::exAsyncPV ( pvInfo & setup, bool preCreateFlag,
|
||||
bool scanOnIn ) :
|
||||
exScalarPV ( setup, preCreateFlag, scanOnIn ),
|
||||
inline exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exScalarPV ( cas, setup, preCreateFlag, scanOnIn ),
|
||||
simultAsychIOCount ( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,8 +141,8 @@ void exVectorPV::scan()
|
||||
*(pF++) = newValue;
|
||||
}
|
||||
|
||||
status = this->update (pDD);
|
||||
if (status!=S_casApp_success) {
|
||||
status = this->update ( *pDD );
|
||||
if ( status != S_casApp_success ) {
|
||||
errMessage (status, "vector scan update failed\n");
|
||||
}
|
||||
}
|
||||
@@ -161,16 +161,8 @@ void exVectorPV::scan()
|
||||
// this may result in too much memory consumtion on
|
||||
// the event queue.
|
||||
//
|
||||
caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
caStatus exVectorPV::updateValue ( const gdd & value )
|
||||
{
|
||||
gddStatus gdds;
|
||||
smartGDDPointer pNewValue;
|
||||
exVecDestructor *pDest;
|
||||
unsigned i;
|
||||
|
||||
if ( ! pValueIn.valid () ) {
|
||||
return S_casApp_undefined;
|
||||
}
|
||||
|
||||
//
|
||||
// Check bounds of incoming request
|
||||
@@ -180,50 +172,47 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// Perhaps much of this is unnecessary since the
|
||||
// server lib checks the bounds of all requests
|
||||
//
|
||||
if (pValueIn->isAtomic()) {
|
||||
if (pValueIn->dimension()!=1u) {
|
||||
if ( value.isAtomic()) {
|
||||
if ( value.dimension() != 1u ) {
|
||||
return S_casApp_badDimension;
|
||||
}
|
||||
const gddBounds* pb = pValueIn->getBounds();
|
||||
if (pb[0u].first()!=0u) {
|
||||
const gddBounds* pb = value.getBounds ();
|
||||
if ( pb[0u].first() != 0u ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
else if (pb[0u].size()>this->info.getElementCount()) {
|
||||
else if ( pb[0u].size() > this->info.getElementCount() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
}
|
||||
else if (!pValueIn->isScalar()) {
|
||||
else if ( ! value.isScalar() ) {
|
||||
//
|
||||
// no containers
|
||||
//
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
aitFloat64 *pF;
|
||||
int gddStatus;
|
||||
|
||||
|
||||
//
|
||||
// Create a new array data descriptor
|
||||
// (so that old values that may be referenced on the
|
||||
// event queue are not replaced)
|
||||
//
|
||||
pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount());
|
||||
if ( ! pNewValue.valid () ) {
|
||||
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount() ) );
|
||||
if ( ! pNewValue.valid() ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// smart pointer class takes care of the reference count
|
||||
// from here down
|
||||
//
|
||||
gddStatus = pNewValue->unreference();
|
||||
assert (!gddStatus);
|
||||
|
||||
gddStatus gdds = pNewValue->unreference( );
|
||||
assert ( ! gdds );
|
||||
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
pF = new aitFloat64 [this->info.getElementCount()];
|
||||
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -233,11 +222,11 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// if no old values exist
|
||||
//
|
||||
unsigned count = this->info.getElementCount();
|
||||
for ( i = 0u; i < count; i++ ) {
|
||||
for ( unsigned i = 0u; i < count; i++ ) {
|
||||
pF[i] = 0.0f;
|
||||
}
|
||||
|
||||
pDest = new exVecDestructor;
|
||||
exVecDestructor * pDest = new exVecDestructor;
|
||||
if (!pDest) {
|
||||
delete [] pF;
|
||||
return S_casApp_noMemory;
|
||||
@@ -247,13 +236,13 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// install the buffer into the DD
|
||||
// (do this before we increment pF)
|
||||
//
|
||||
pNewValue->putRef(pF, pDest);
|
||||
pNewValue->putRef ( pF, pDest );
|
||||
|
||||
//
|
||||
// copy in the values that they are writing
|
||||
//
|
||||
gdds = pNewValue->put( & (*pValueIn) );
|
||||
if (gdds) {
|
||||
gdds = pNewValue->put( & value );
|
||||
if ( gdds ) {
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
|
||||
@@ -267,8 +256,8 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exVecDestructor::run (void *pUntyped)
|
||||
void exVecDestructor::run ( void *pUntyped )
|
||||
{
|
||||
aitFloat32 *pf = (aitFloat32 *) pUntyped;
|
||||
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
|
||||
delete [] pf;
|
||||
}
|
||||
|
||||
@@ -25,37 +25,40 @@ extern int main (int argc, const char **argv)
|
||||
double executionTime;
|
||||
char pvPrefix[128] = "";
|
||||
unsigned aliasCount = 1u;
|
||||
unsigned scanOnAsUnsignedInt = true;
|
||||
unsigned scanOn = true;
|
||||
unsigned syncScan = true;
|
||||
char arraySize[64] = "";
|
||||
bool scanOn;
|
||||
bool forever = true;
|
||||
int i;
|
||||
|
||||
for ( i = 1; i < argc; i++ ) {
|
||||
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
|
||||
if ( sscanf(argv[i], "-d %u", & debugLevel ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-t %lf", &executionTime)==1) {
|
||||
if ( sscanf ( argv[i],"-t %lf", & executionTime ) == 1 ) {
|
||||
forever = false;
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-p %127s", pvPrefix)==1) {
|
||||
if ( sscanf ( argv[i], "-p %127s", pvPrefix ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-c %u", &aliasCount)==1) {
|
||||
if ( sscanf ( argv[i],"-c %u", & aliasCount ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-s %u", &scanOnAsUnsignedInt)==1) {
|
||||
if ( sscanf ( argv[i],"-s %u", & scanOn ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-a %63s", arraySize)==1) {
|
||||
if ( sscanf ( argv[i],"-a %63s", arraySize ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-ss %u", & syncScan ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
printf ("\"%s\"?\n", argv[i]);
|
||||
printf (
|
||||
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> "
|
||||
"-c<numbered alias count> -s<1=scan on (default), 0=scan off]> "
|
||||
"-a<max array size>]\n",
|
||||
"-c<numbered alias count> -s<1=scan on (default), 0=scan off> "
|
||||
"-ss<1=synchronous scan (default), 0=asynchronous scan>]\n",
|
||||
argv[0]);
|
||||
|
||||
return (1);
|
||||
@@ -65,15 +68,9 @@ extern int main (int argc, const char **argv)
|
||||
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", arraySize );
|
||||
}
|
||||
|
||||
if (scanOnAsUnsignedInt) {
|
||||
scanOn = true;
|
||||
}
|
||||
else {
|
||||
scanOn = false;
|
||||
}
|
||||
|
||||
try {
|
||||
pCAS = new exServer ( pvPrefix, aliasCount, scanOn );
|
||||
pCAS = new exServer ( pvPrefix, aliasCount,
|
||||
scanOn != 0, syncScan == 0 );
|
||||
}
|
||||
catch ( ... ) {
|
||||
errlogPrintf ( "Server initialization error\n" );
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "fdManager.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caServerI.h"
|
||||
#include "beaconAnomalyGovernor.h"
|
||||
#include "beaconTimer.h"
|
||||
#include "server.h"
|
||||
|
||||
//
|
||||
// the minimum period between beacon anomalies
|
||||
|
||||
@@ -19,9 +19,20 @@
|
||||
#ifndef beaconAnomalyGovernorh
|
||||
#define beaconAnomalyGovernorh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_beaconAnomalyGovernorh
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
// external headers included here
|
||||
#include "epicsTimer.h"
|
||||
#include "epicsMutex.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_beaconAnomalyGovernorh
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
class caServerI;
|
||||
|
||||
class beaconAnomalyGovernor : public epicsTimerNotify {
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "fdManager.h"
|
||||
#include "envDefs.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caServerI.h"
|
||||
#include "beaconTimer.h"
|
||||
|
||||
// the maximum beacon period if EPICS_CA_BEACON_PERIOD isnt available
|
||||
|
||||
@@ -19,14 +19,22 @@
|
||||
#ifndef beaconTimerh
|
||||
#define beaconTimerh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_beaconTimerh
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
// external headers included here
|
||||
#include "epicsTimer.h"
|
||||
#include "caProto.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_beaconTimerh
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
class caServerI;
|
||||
|
||||
//
|
||||
// beaconTimer
|
||||
//
|
||||
class beaconTimer : public epicsTimerNotify {
|
||||
public:
|
||||
beaconTimer ( caServerI & casIn );
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef includeCaCommonDefH
|
||||
#define includeCaCommonDefH
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef NELEMENTS
|
||||
#define NELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(A,B) ((A)>(B)?(B):(A))
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(A,B) ((A)<(B)?(B):(A))
|
||||
#endif
|
||||
|
||||
#endif /* ifndef includeCaCommonDefH (last line in this file) */
|
||||
|
||||
@@ -171,12 +171,12 @@ struct sockaddr caNetAddr::getSock() const
|
||||
|
||||
caNetAddr::operator sockaddr_in () const
|
||||
{
|
||||
return this->getSockIP();
|
||||
return this->getSockIP ();
|
||||
}
|
||||
|
||||
caNetAddr::operator sockaddr () const
|
||||
{
|
||||
return this->getSock();
|
||||
return this->getSock ();
|
||||
}
|
||||
|
||||
void caNetAddr::selfTest ()
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
// caNetAddr
|
||||
//
|
||||
// special cas specific network address class so:
|
||||
// 1) we dont drag BSD socket headers into
|
||||
// the server tool
|
||||
// 1) we dont drag BSD socket headers into the server tool
|
||||
// 2) we are not prevented from using other networking services
|
||||
// besides sockets in the future
|
||||
// besides sockets in the future
|
||||
//
|
||||
|
||||
#ifndef caNetAddrH
|
||||
@@ -30,6 +29,8 @@
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
# endif
|
||||
#else
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
class epicsShareClass caNetAddr {
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
#include "fdManager.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caServerI.h"
|
||||
|
||||
//
|
||||
// caServer::caServer()
|
||||
//
|
||||
caServer::caServer ()
|
||||
{
|
||||
static bool init = false;
|
||||
@@ -33,12 +31,9 @@ caServer::caServer ()
|
||||
init = true;
|
||||
}
|
||||
|
||||
this->pCAS = new caServerI(*this);
|
||||
this->pCAS = new caServerI ( *this );
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::~caServer()
|
||||
//
|
||||
caServer::~caServer()
|
||||
{
|
||||
if (this->pCAS) {
|
||||
@@ -47,36 +42,22 @@ caServer::~caServer()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::pvExistTest()
|
||||
//
|
||||
pvExistReturn caServer::pvExistTest (const casCtx &, const char *)
|
||||
{
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::createPV()
|
||||
//
|
||||
pvCreateReturn caServer::createPV (const casCtx &, const char *)
|
||||
{
|
||||
return S_casApp_pvNotFound;
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::pvAttach()
|
||||
//
|
||||
pvAttachReturn caServer::pvAttach (const casCtx &ctx, const char *pAliasName)
|
||||
{
|
||||
//
|
||||
// remain backwards compatible (call deprecated routine)
|
||||
//
|
||||
return this->createPV(ctx, pAliasName);
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::registerEvent()
|
||||
//
|
||||
casEventMask caServer::registerEvent (const char *pName) // X aCC 361
|
||||
{
|
||||
if (this->pCAS) {
|
||||
@@ -89,9 +70,6 @@ casEventMask caServer::registerEvent (const char *pName) // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::show()
|
||||
//
|
||||
void caServer::show(unsigned level) const
|
||||
{
|
||||
if (this->pCAS) {
|
||||
@@ -102,9 +80,6 @@ void caServer::show(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::setDebugLevel()
|
||||
//
|
||||
void caServer::setDebugLevel (unsigned level)
|
||||
{
|
||||
if (pCAS) {
|
||||
@@ -115,9 +90,6 @@ void caServer::setDebugLevel (unsigned level)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::getDebugLevel()
|
||||
//
|
||||
unsigned caServer::getDebugLevel () const // X aCC 361
|
||||
{
|
||||
if (pCAS) {
|
||||
@@ -129,9 +101,6 @@ unsigned caServer::getDebugLevel () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::valueEventMask ()
|
||||
//
|
||||
casEventMask caServer::valueEventMask () const // X aCC 361
|
||||
{
|
||||
if (pCAS) {
|
||||
@@ -143,9 +112,6 @@ casEventMask caServer::valueEventMask () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::logEventMask ()
|
||||
//
|
||||
casEventMask caServer::logEventMask () const // X aCC 361
|
||||
{
|
||||
if (pCAS) {
|
||||
@@ -157,44 +123,32 @@ casEventMask caServer::logEventMask () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::alarmEventMask ()
|
||||
//
|
||||
casEventMask caServer::alarmEventMask () const // X aCC 361
|
||||
{
|
||||
if (pCAS) {
|
||||
return this->pCAS->alarmEventMask();
|
||||
if ( pCAS ) {
|
||||
return this->pCAS->alarmEventMask ();
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
return casEventMask();
|
||||
printf ( "caServer:: no server internals attached\n" );
|
||||
return casEventMask ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::alarmEventMask ()
|
||||
//
|
||||
class epicsTimer & caServer::createTimer ()
|
||||
{
|
||||
return fileDescriptorManager.createTimer ();
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::subscriptionEventsProcessed
|
||||
//
|
||||
unsigned caServer::subscriptionEventsProcessed () const // X aCC 361
|
||||
{
|
||||
if ( pCAS ) {
|
||||
return this->pCAS->subscriptionEventsProcessed();
|
||||
return this->pCAS->subscriptionEventsProcessed ();
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServer::subscriptionEventsPosted
|
||||
//
|
||||
unsigned caServer::subscriptionEventsPosted () const // X aCC 361
|
||||
{
|
||||
if ( pCAS ) {
|
||||
@@ -211,22 +165,3 @@ void caServer::generateBeaconAnomaly ()
|
||||
this->pCAS->generateBeaconAnomaly ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casRes::~casRes()
|
||||
//
|
||||
// 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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -22,33 +22,34 @@
|
||||
|
||||
#include "addrList.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#define caServerGlobal
|
||||
#include "server.h"
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "caServerI.h"
|
||||
#include "beaconTimer.h"
|
||||
#include "beaconAnomalyGovernor.h"
|
||||
#include "casStreamOS.h"
|
||||
#include "casIntfOS.h"
|
||||
|
||||
// include a version string for POSIX systems
|
||||
static const char * pVersionCAS =
|
||||
"@(#) " EPICS_VERSION_STRING ", CA Portable Server Library "
|
||||
"@(#) " EPICS_VERSION_STRING
|
||||
", CA Portable Server Library "
|
||||
"$Date$";
|
||||
|
||||
//
|
||||
// caServerI::caServerI()
|
||||
//
|
||||
caServerI::caServerI (caServer &tool) :
|
||||
caServerI::caServerI ( caServer & tool ) :
|
||||
adapter (tool),
|
||||
beaconTmr ( * new beaconTimer ( *this ) ),
|
||||
beaconAnomalyGov ( * new beaconAnomalyGovernor ( *this ) ),
|
||||
debugLevel (0u),
|
||||
nEventsProcessed (0u),
|
||||
nEventsPosted (0u)
|
||||
debugLevel ( 0u ),
|
||||
nEventsProcessed ( 0u ),
|
||||
nEventsPosted ( 0u )
|
||||
{
|
||||
assert ( & adapter != NULL );
|
||||
|
||||
// create predefined event types
|
||||
this->valueEvent = registerEvent ("value");
|
||||
this->logEvent = registerEvent ("log");
|
||||
this->alarmEvent = registerEvent ("alarm");
|
||||
this->valueEvent = registerEvent ( "value" );
|
||||
this->logEvent = registerEvent ( "log" );
|
||||
this->alarmEvent = registerEvent ( "alarm" );
|
||||
|
||||
this->locateInterfaces ();
|
||||
|
||||
@@ -61,26 +62,14 @@ caServerI::caServerI (caServer &tool) :
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* caServerI::~caServerI()
|
||||
*/
|
||||
caServerI::~caServerI()
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
|
||||
delete & this->beaconAnomalyGov;
|
||||
delete & this->beaconTmr;
|
||||
|
||||
// delete all clients
|
||||
tsDLIter <casStrmClient> iter = this->clientList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
tsDLIter <casStrmClient> tmp = iter;
|
||||
++tmp;
|
||||
//
|
||||
// destructor takes client out of list
|
||||
//
|
||||
delete iter.pointer ();
|
||||
iter = tmp;
|
||||
while ( casStrmClient * pClient = this->clientList.get() ) {
|
||||
delete pClient;
|
||||
}
|
||||
|
||||
casIntfOS *pIF;
|
||||
@@ -89,40 +78,29 @@ caServerI::~caServerI()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::installClient()
|
||||
//
|
||||
void caServerI::installClient(casStrmClient *pClient)
|
||||
void caServerI::destroyClient ( casStrmClient & client )
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->clientList.add(*pClient);
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->clientList.remove ( client );
|
||||
}
|
||||
delete & client;
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::removeClient()
|
||||
//
|
||||
void caServerI::removeClient (casStrmClient *pClient)
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->clientList.remove (*pClient);
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::connectCB()
|
||||
//
|
||||
void caServerI::connectCB ( casIntfOS & intf )
|
||||
{
|
||||
casStreamOS * pClient = intf.newStreamClient ( *this, this->clientBufMemMgr );
|
||||
if ( pClient ) {
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->clientList.add ( *pClient );
|
||||
}
|
||||
pClient->sendVersion ();
|
||||
pClient->flush ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casVerifyFunc()
|
||||
//
|
||||
void casVerifyFunc (const char *pFile, unsigned line, const char *pExp)
|
||||
void casVerifyFunc ( const char * pFile, unsigned line, const char * pExp )
|
||||
{
|
||||
fprintf(stderr, "the expression \"%s\" didnt evaluate to boolean true \n",
|
||||
pExp);
|
||||
@@ -133,9 +111,6 @@ void casVerifyFunc (const char *pFile, unsigned line, const char *pExp)
|
||||
"Please forward above text to johill@lanl.gov - thanks\n");
|
||||
}
|
||||
|
||||
//
|
||||
// serverToolDebugFunc()
|
||||
//
|
||||
void serverToolDebugFunc (const char *pFile, unsigned line, const char *pComment)
|
||||
{
|
||||
fprintf (stderr,
|
||||
@@ -143,9 +118,6 @@ void serverToolDebugFunc (const char *pFile, unsigned line, const char *pComment
|
||||
line, pFile, pComment);
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::attachInterface()
|
||||
//
|
||||
caStatus caServerI::attachInterface ( const caNetAddr & addrIn,
|
||||
bool autoBeaconAddr, bool addConfigBeaconAddr)
|
||||
{
|
||||
@@ -160,14 +132,10 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn,
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::sendBeacon()
|
||||
// send a beacon over each configured address
|
||||
//
|
||||
void caServerI::sendBeacon ( ca_uint32_t beaconNo )
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
tsDLIter <casIntfOS> iter = this->intfList.firstIter ();
|
||||
tsDLIter < casIntfOS > iter = this->intfList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->sendBeacon ( beaconNo );
|
||||
iter++;
|
||||
@@ -179,47 +147,36 @@ void caServerI::generateBeaconAnomaly ()
|
||||
this->beaconAnomalyGov.start ();
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::lookupMonitor ()
|
||||
//
|
||||
casMonitor * caServerI::lookupMonitor ( const caResId &idIn )
|
||||
void caServerI::destroyMonitor ( casMonitor & mon )
|
||||
{
|
||||
chronIntId tmpId ( idIn );
|
||||
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
casRes * pRes = this->chronIntIdResTable<casRes>::lookup ( tmpId );
|
||||
if ( pRes ) {
|
||||
if ( pRes->resourceType() == casMonitorT ) {
|
||||
// ok to avoid overhead of dynamic cast here because
|
||||
// type code was checked above
|
||||
return static_cast < casMonitor * > ( pRes );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
mon.~casMonitor ();
|
||||
this->casMonitorFreeList.release ( & mon );
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::lookupChannel ()
|
||||
//
|
||||
casChannelI * caServerI::lookupChannel ( const caResId &idIn )
|
||||
void caServerI::updateEventsPostedCounter ( unsigned nNewPosts )
|
||||
{
|
||||
chronIntId tmpId ( idIn );
|
||||
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
casRes * pRes = this->chronIntIdResTable<casRes>::lookup ( tmpId );
|
||||
if ( pRes ) {
|
||||
if ( pRes->resourceType() == casChanT ) {
|
||||
// ok to avoid overhead of dynamic cast here because
|
||||
// type code was checked above
|
||||
return static_cast < casChannelI * > ( pRes );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex );
|
||||
this->nEventsPosted += nNewPosts;
|
||||
}
|
||||
|
||||
unsigned caServerI::subscriptionEventsPosted () const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex );
|
||||
return this->nEventsPosted;
|
||||
}
|
||||
|
||||
void caServerI::incrEventsProcessedCounter ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex );
|
||||
this->nEventsProcessed ++;
|
||||
}
|
||||
|
||||
unsigned caServerI::subscriptionEventsProcessed () const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex );
|
||||
return this->nEventsProcessed;
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::show()
|
||||
//
|
||||
void caServerI::show (unsigned level) const
|
||||
{
|
||||
int bytes_reserved;
|
||||
@@ -232,13 +189,13 @@ void caServerI::show (unsigned level) const
|
||||
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
tsDLIterConst<casStrmClient> iterCl = this->clientList.firstIter ();
|
||||
tsDLIterConst < casStrmClient > iterCl = this->clientList.firstIter ();
|
||||
while ( iterCl.valid () ) {
|
||||
iterCl->show (level);
|
||||
iterCl->show ( level );
|
||||
++iterCl;
|
||||
}
|
||||
|
||||
tsDLIterConst<casIntfOS> iterIF = this->intfList.firstIter ();
|
||||
tsDLIterConst < casIntfOS > iterIF = this->intfList.firstIter ();
|
||||
while ( iterIF.valid () ) {
|
||||
iterIF->casIntfOS::show ( level );
|
||||
++iterIF;
|
||||
@@ -270,22 +227,34 @@ void caServerI::show (unsigned level) const
|
||||
#endif
|
||||
printf(
|
||||
"The server's integer resource id conversion table:\n");
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->chronIntIdResTable<casRes>::show(level);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventRegistry::~casEventRegistry()
|
||||
//
|
||||
// (must not be inline because it is virtual)
|
||||
//
|
||||
casMonitor & caServerI::casMonitorFactory (
|
||||
casChannelI & chan, caResId clientId,
|
||||
const unsigned long count, const unsigned type,
|
||||
const casEventMask & mask,
|
||||
casMonitorCallbackInterface & cb )
|
||||
{
|
||||
casMonitor * pMon =
|
||||
new ( this->casMonitorFreeList ) casMonitor
|
||||
( clientId, chan, count, type, mask, cb );
|
||||
return *pMon;
|
||||
}
|
||||
|
||||
void caServerI::casMonitorDestroy ( casMonitor & cm )
|
||||
{
|
||||
cm.~casMonitor ();
|
||||
this->casMonitorFreeList.release ( & cm );
|
||||
}
|
||||
|
||||
casEventRegistry::~casEventRegistry()
|
||||
{
|
||||
this->traverse ( &casEventMaskEntry::destroy );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,34 +15,26 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casAsyncIOI.h"
|
||||
|
||||
//
|
||||
// casAsyncIOI::casAsyncIOI()
|
||||
//
|
||||
casAsyncIOI::casAsyncIOI ( const casCtx & ctx ) :
|
||||
client ( *ctx.getClient() ), inTheEventQueue ( false ),
|
||||
posted ( false ), ioComplete ( false ),
|
||||
serverDelete ( false ), duplicate ( false )
|
||||
posted ( false ), ioComplete ( false )
|
||||
{
|
||||
//
|
||||
// catch situation where they create more than one
|
||||
// async IO object per request
|
||||
//
|
||||
if ( ! client.okToStartAsynchIO () ) {
|
||||
errMessage ( S_cas_badParameter,
|
||||
"- duplicate async IO creation" );
|
||||
this->duplicate = true;
|
||||
throw std::logic_error (
|
||||
"server tool attempted to "
|
||||
"start duplicate asynchronous IO" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::~casAsyncIOI()
|
||||
//
|
||||
// ways this gets destroyed:
|
||||
// 1) io completes, this is pulled off the queue, and result
|
||||
@@ -71,92 +63,54 @@ casAsyncIOI::casAsyncIOI ( const casCtx & ctx ) :
|
||||
//
|
||||
casAsyncIOI::~casAsyncIOI()
|
||||
{
|
||||
if ( ! this->serverDelete ) {
|
||||
fprintf(stderr,
|
||||
"WARNING: An async IO operation was deleted prematurely\n");
|
||||
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");
|
||||
fprintf(stderr,
|
||||
"WARNING: IO by posting S_casApp_canceledAsyncIO instead of\n");
|
||||
fprintf(stderr,
|
||||
"WARNING: by deleting the async IO object.\n");
|
||||
}
|
||||
|
||||
//
|
||||
// pulls itself out of the event queue
|
||||
// if it is installed there.
|
||||
//
|
||||
this->client.removeFromEventQueue ( *this );
|
||||
this->client.removeFromEventQueue ( *this, this->inTheEventQueue );
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::cbFunc()
|
||||
// o called when IO completion event reaches top of event queue
|
||||
// o clients lock is applied when calling this
|
||||
//
|
||||
caStatus casAsyncIOI::cbFunc ( casCoreClient & )
|
||||
caStatus casAsyncIOI::cbFunc (
|
||||
casCoreClient &, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->inTheEventQueue = false;
|
||||
|
||||
caStatus status = this->cbFuncAsyncIO();
|
||||
caStatus status = S_cas_success;
|
||||
{
|
||||
this->inTheEventQueue = false;
|
||||
|
||||
if (status == S_cas_sendBlocked) {
|
||||
//
|
||||
// causes this op to be pushed back on the queue
|
||||
//
|
||||
this->inTheEventQueue = true;
|
||||
return status;
|
||||
}
|
||||
else if (status != S_cas_success) {
|
||||
errMessage (status, "Asynch IO completion failed");
|
||||
}
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unlocker ( guard );
|
||||
status = this->cbFuncAsyncIO ();
|
||||
}
|
||||
|
||||
this->ioComplete = true;
|
||||
if ( status == S_cas_sendBlocked ) {
|
||||
//
|
||||
// causes this op to be pushed back on the queue
|
||||
//
|
||||
this->inTheEventQueue = true;
|
||||
return status;
|
||||
}
|
||||
else if ( status != S_cas_success ) {
|
||||
errMessage ( status, "Asynch IO completion failed" );
|
||||
}
|
||||
|
||||
//
|
||||
// dont use "this" after potentially destroying the
|
||||
// object here
|
||||
//
|
||||
this->serverDestroy();
|
||||
this->ioComplete = true;
|
||||
}
|
||||
|
||||
this->client.getCAS().ioBlockedList::signal ();
|
||||
|
||||
// dont use "this" after destroying the object here
|
||||
delete this;
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
void casAsyncIOI::eventSysDestroyNotify ( casCoreClient & )
|
||||
caStatus casAsyncIOI::insertEventQueue ()
|
||||
{
|
||||
this->serverDestroy();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::postIOCompletionI ()
|
||||
//
|
||||
caStatus casAsyncIOI::postIOCompletionI ()
|
||||
{
|
||||
//
|
||||
// detect the case where the server called destroy(),
|
||||
// the server tool postponed deletion of the object,
|
||||
// and then it called postIOCompletion() on this object
|
||||
// when it was currently not in use by the server.
|
||||
//
|
||||
if ( this->serverDelete ) {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
|
||||
// this is only touched in the constructor so its
|
||||
// ok not to not take a lock here
|
||||
if ( this->duplicate ) {
|
||||
errMessage ( S_cas_badParameter,
|
||||
"- duplicate async IO");
|
||||
//
|
||||
// dont use "this" after potentially destroying the
|
||||
// object here
|
||||
//
|
||||
this->serverDestroy();
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
|
||||
//
|
||||
// place this event in the event queue
|
||||
// o this also signals the event consumer
|
||||
@@ -165,55 +119,12 @@ caStatus casAsyncIOI::postIOCompletionI ()
|
||||
return this->client.addToEventQueue ( *this, this->inTheEventQueue, this->posted );
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::getCAS()
|
||||
// (not inline because this is used by the interface class)
|
||||
//
|
||||
caServer *casAsyncIOI::getCAS() const
|
||||
{
|
||||
return this->client.getCAS().getAdapter();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::readOP()
|
||||
//
|
||||
bool casAsyncIOI::readOP() const
|
||||
bool casAsyncIOI::oneShotReadOP() const
|
||||
{
|
||||
//
|
||||
// not a read op
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncIOI::serverDestroyIfReadOP()
|
||||
// o clients lock is held when this is called
|
||||
//
|
||||
void casAsyncIOI::serverDestroyIfReadOP()
|
||||
{
|
||||
if ( this->readOP() ) {
|
||||
this->serverDestroy();
|
||||
}
|
||||
|
||||
//
|
||||
// NO REF TO THIS OBJECT BELOW HERE
|
||||
// BECAUSE OF THE DELETE ABOVE
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncIOI::serverDestroy ()
|
||||
//
|
||||
void casAsyncIOI::serverDestroy ()
|
||||
{
|
||||
this->serverDelete = true;
|
||||
this->destroy();
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncIOI::destroy ()
|
||||
//
|
||||
void casAsyncIOI::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
@@ -15,83 +15,51 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
#include <stdexcept>
|
||||
|
||||
//
|
||||
// casAsyncPVAttachIO::casAsyncPVAttachIO()
|
||||
//
|
||||
casAsyncPVAttachIO::casAsyncPVAttachIO (const casCtx &ctx) :
|
||||
casAsyncIOI ( ctx ),
|
||||
msg ( *ctx.getMsg() ),
|
||||
retVal ( S_cas_badParameter )
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casAsyncPVAttachIOI.h"
|
||||
|
||||
casAsyncPVAttachIO::casAsyncPVAttachIO ( const casCtx &ctx ) :
|
||||
pAsyncPVAttachIOI ( new casAsyncPVAttachIOI ( *this, ctx ) )
|
||||
{
|
||||
this->client.installAsyncIO ( *this );
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVAttachIO::~casAsyncPVAttachIO()
|
||||
//
|
||||
void casAsyncPVAttachIO::serverInitiatedDestroy ()
|
||||
{
|
||||
this->pAsyncPVAttachIOI = 0;
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
casAsyncPVAttachIO::~casAsyncPVAttachIO ()
|
||||
{
|
||||
this->client.removeAsyncIO ( *this );
|
||||
if ( this->pAsyncPVAttachIOI ) {
|
||||
throw std::logic_error (
|
||||
"the server library *must* initiate asynchronous IO destroy" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVAttachIO::postIOCompletion()
|
||||
//
|
||||
caStatus casAsyncPVAttachIO::postIOCompletion ( const pvAttachReturn & retValIn )
|
||||
{
|
||||
this->retVal = retValIn;
|
||||
return this->postIOCompletionI ();
|
||||
if ( this->pAsyncPVAttachIOI ) {
|
||||
return this->pAsyncPVAttachIOI->postIOCompletion ( retValIn );
|
||||
}
|
||||
else {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVAttachIO::cbFuncAsyncIO()
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
caStatus casAsyncPVAttachIO::cbFuncAsyncIO()
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
switch ( this->msg.m_cmmd ) {
|
||||
case CA_PROTO_CLAIM_CIU:
|
||||
status = this->client.createChanResponse ( this->msg, this->retVal );
|
||||
break;
|
||||
|
||||
default:
|
||||
errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__,
|
||||
" - client request type = %u", this->msg.m_cmmd );
|
||||
status = S_cas_invalidAsynchIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncPVAttachIO::destroy ()
|
||||
//
|
||||
void casAsyncPVAttachIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// deprecated
|
||||
//
|
||||
casAsyncPVCreateIO::casAsyncPVCreateIO ( const casCtx & ctx ) :
|
||||
casAsyncPVAttachIO ( ctx )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// deprecated
|
||||
//
|
||||
casAsyncPVCreateIO::~casAsyncPVCreateIO ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,71 +15,39 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casAsyncPVExistIOI.h"
|
||||
|
||||
//
|
||||
// casAsyncPVExistIO::casAsyncPVExistIO()
|
||||
//
|
||||
casAsyncPVExistIO::casAsyncPVExistIO (const casCtx &ctx) :
|
||||
casAsyncIOI ( ctx ),
|
||||
msg ( *ctx.getMsg () ),
|
||||
retVal (pverDoesNotExistHere),
|
||||
dgOutAddr ( ctx.getClient ()->fetchLastRecvAddr () ),
|
||||
protocolRevision ( ctx.getClient ()->protocolRevision () ),
|
||||
sequenceNumber ( ctx.getClient ()->datagramSequenceNumber () )
|
||||
casAsyncPVExistIO::casAsyncPVExistIO ( const casCtx & ctx ) :
|
||||
pAsyncPVExistIOI ( new casAsyncPVExistIOI ( *this, ctx ) ) {}
|
||||
|
||||
void casAsyncPVExistIO::serverInitiatedDestroy ()
|
||||
{
|
||||
this->client.installAsyncIO (*this);
|
||||
this->pAsyncPVExistIOI = 0;
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVExistIO::~casAsyncPVExistIO ()
|
||||
//
|
||||
casAsyncPVExistIO::~casAsyncPVExistIO ()
|
||||
{
|
||||
this->client.removeAsyncIO (*this);
|
||||
if ( this->pAsyncPVExistIOI ) {
|
||||
throw std::logic_error (
|
||||
"the server library *must* initiate asynchronous IO destroy" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVExistIO::postIOCompletion ()
|
||||
//
|
||||
caStatus casAsyncPVExistIO::postIOCompletion (const pvExistReturn &retValIn)
|
||||
caStatus casAsyncPVExistIO::postIOCompletion ( const pvExistReturn & retValIn )
|
||||
{
|
||||
this->retVal = retValIn;
|
||||
return this->postIOCompletionI ();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVExistIO::cbFuncAsyncIO()
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
caStatus casAsyncPVExistIO::cbFuncAsyncIO()
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
if (this->msg.m_cmmd==CA_PROTO_SEARCH) {
|
||||
//
|
||||
// pass output DG address parameters
|
||||
//
|
||||
status = this->client.asyncSearchResponse (
|
||||
this->dgOutAddr, this->msg, this->retVal,
|
||||
this->protocolRevision, this->sequenceNumber );
|
||||
if ( this->pAsyncPVExistIOI ) {
|
||||
return this->pAsyncPVExistIOI->postIOCompletion ( retValIn );
|
||||
}
|
||||
else {
|
||||
errPrintf (S_cas_invalidAsynchIO, __FILE__, __LINE__,
|
||||
" - client request type = %u", this->msg.m_cmmd);
|
||||
status = S_cas_invalidAsynchIO;
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncPVExistIO::destroy ()
|
||||
//
|
||||
void casAsyncPVExistIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
|
||||
@@ -15,113 +15,45 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "dbMapper.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtxI in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casAsyncReadIOI.h"
|
||||
|
||||
//
|
||||
// casAsyncReadIO::casAsyncReadIO()
|
||||
//
|
||||
casAsyncReadIO::casAsyncReadIO ( const casCtx & ctx ) :
|
||||
casAsyncIOI ( ctx ), msg ( *ctx.getMsg() ),
|
||||
chan ( *ctx.getChannel () ), pDD ( NULL ), completionStatus ( S_cas_internal )
|
||||
pAsyncReadIOI ( new casAsyncReadIOI ( *this, ctx ) ) {}
|
||||
|
||||
void casAsyncReadIO::serverInitiatedDestroy ()
|
||||
{
|
||||
assert ( & this->chan );
|
||||
this->chan.installAsyncIO ( *this );
|
||||
this->pAsyncReadIOI = 0;
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncReadIO::~casAsyncReadIO()
|
||||
//
|
||||
casAsyncReadIO::~casAsyncReadIO ()
|
||||
{
|
||||
this->chan.removeAsyncIO ( *this );
|
||||
if ( this->pAsyncReadIOI ) {
|
||||
throw std::logic_error (
|
||||
"the server library *must* initiate asynchronous IO destroy" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncReadIO::postIOCompletion()
|
||||
//
|
||||
caStatus casAsyncReadIO::postIOCompletion ( caStatus completionStatusIn,
|
||||
const gdd & valueRead)
|
||||
caStatus casAsyncReadIO::postIOCompletion (
|
||||
caStatus completionStatusIn, const gdd & valueRead )
|
||||
{
|
||||
this->pDD = & valueRead;
|
||||
this->completionStatus = completionStatusIn;
|
||||
return this->postIOCompletionI ();
|
||||
if ( this->pAsyncReadIOI ) {
|
||||
return this->pAsyncReadIOI->postIOCompletion (
|
||||
completionStatusIn, valueRead );
|
||||
}
|
||||
else {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncReadIO::readOP()
|
||||
//
|
||||
bool casAsyncReadIO::readOP () const
|
||||
{
|
||||
return true; // it is a read op
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncReadIO::cbFuncAsyncIO()
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
caStatus casAsyncReadIO::cbFuncAsyncIO()
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
switch ( this->msg.m_cmmd ) {
|
||||
case CA_PROTO_READ:
|
||||
status = client.readResponse ( &this->chan, this->msg,
|
||||
*this->pDD, this->completionStatus);
|
||||
break;
|
||||
|
||||
case CA_PROTO_READ_NOTIFY:
|
||||
status = client.readNotifyResponse ( &this->chan,
|
||||
this->msg, this->pDD,
|
||||
this->completionStatus);
|
||||
break;
|
||||
|
||||
case CA_PROTO_EVENT_ADD:
|
||||
status = client.monitorResponse ( this->chan,
|
||||
this->msg, this->pDD,
|
||||
this->completionStatus);
|
||||
break;
|
||||
|
||||
case CA_PROTO_CLAIM_CIU:
|
||||
unsigned nativeTypeDBR;
|
||||
status = this->chan.getPVI().bestDBRType ( nativeTypeDBR );
|
||||
if ( status ) {
|
||||
errMessage ( status, "best external dbr type fetch failed" );
|
||||
status = client.channelCreateFailedResp ( this->msg, status );
|
||||
}
|
||||
else {
|
||||
// we end up here if the channel claim protocol response is delayed
|
||||
// by an asynchronous enum string table fetch response
|
||||
if ( this->completionStatus == S_cas_success && this->pDD.valid() ) {
|
||||
this->chan.getPVI().updateEnumStringTableAsyncCompletion ( *this->pDD );
|
||||
}
|
||||
else {
|
||||
errMessage ( this->completionStatus,
|
||||
"unable to read application type \"enums\" string"
|
||||
" conversion table for enumerated PV" );
|
||||
}
|
||||
status = client.enumPostponedCreateChanResponse ( this->chan,
|
||||
this->msg, nativeTypeDBR );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__,
|
||||
" - client request type = %u", this->msg.m_cmmd );
|
||||
status = S_cas_invalidAsynchIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncReadIO::destroy ()
|
||||
//
|
||||
void casAsyncReadIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,73 +15,41 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casAsyncWriteIOI.h"
|
||||
|
||||
//
|
||||
// casAsyncWriteIO::casAsyncWriteIO()
|
||||
//
|
||||
casAsyncWriteIO::casAsyncWriteIO ( const casCtx & ctx ) :
|
||||
casAsyncIOI ( ctx ),
|
||||
msg ( *ctx.getMsg() ),
|
||||
chan ( *ctx.getChannel() ),
|
||||
completionStatus ( S_cas_internal )
|
||||
pAsyncWriteIOI ( new casAsyncWriteIOI ( *this, ctx ) )
|
||||
{
|
||||
assert ( &this->chan );
|
||||
this->chan.installAsyncIO ( *this );
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncWriteIO::~casAsyncWriteIO()
|
||||
//
|
||||
void casAsyncWriteIO::serverInitiatedDestroy ()
|
||||
{
|
||||
this->pAsyncWriteIOI = 0;
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
casAsyncWriteIO::~casAsyncWriteIO()
|
||||
{
|
||||
this->chan.removeAsyncIO ( *this );
|
||||
if ( this->pAsyncWriteIOI ) {
|
||||
throw std::logic_error (
|
||||
"the server library *must* initiate asynchronous IO destroy" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncWriteIO::postIOCompletion()
|
||||
//
|
||||
caStatus casAsyncWriteIO::postIOCompletion ( caStatus completionStatusIn )
|
||||
{
|
||||
this->completionStatus = completionStatusIn;
|
||||
return this->postIOCompletionI ();
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncWriteIO::cbFuncAsyncIO()
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
caStatus casAsyncWriteIO::cbFuncAsyncIO ()
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
switch ( this->msg.m_cmmd ) {
|
||||
case CA_PROTO_WRITE:
|
||||
status = client.writeResponse ( this->msg,
|
||||
this->completionStatus );
|
||||
break;
|
||||
|
||||
case CA_PROTO_WRITE_NOTIFY:
|
||||
status = client.writeNotifyResponse (
|
||||
this->msg, this->completionStatus );
|
||||
break;
|
||||
|
||||
default:
|
||||
errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__,
|
||||
" - client request type = %u", this->msg.m_cmmd );
|
||||
status = S_cas_invalidAsynchIO;
|
||||
break;
|
||||
if ( this->pAsyncWriteIOI ) {
|
||||
return this->pAsyncWriteIOI->postIOCompletion ( completionStatusIn );
|
||||
}
|
||||
else {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// void casAsyncWriteIO::destroy ()
|
||||
//
|
||||
void casAsyncWriteIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
#include "envDefs.h"
|
||||
#include "freeList.h"
|
||||
#include "errlog.h"
|
||||
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "clientBufMemoryManager.h"
|
||||
#include "caProto.h"
|
||||
|
||||
casBufferFactory::casBufferFactory () :
|
||||
smallBufFreeList ( 0 ), largeBufFreeList ( 0 ), largeBufferSizePriv ( 0u )
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
|
||||
//
|
||||
// casChanDelEv()
|
||||
//
|
||||
casChanDelEv::~casChanDelEv()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casChanDelEv()
|
||||
//
|
||||
caStatus casChanDelEv::cbFunc ( casCoreClient & client )
|
||||
{
|
||||
caStatus status;
|
||||
status = client.disconnectChan ( this->id );
|
||||
if ( status == S_cas_success ) {
|
||||
delete this;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void casChanDelEv::eventSysDestroyNotify ( casCoreClient & )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
@@ -15,43 +15,30 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI inline func
|
||||
#include "casPVListChanIL.h" // casPVListChan inline func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casChannelI.h"
|
||||
|
||||
//
|
||||
// casChannel::casChannel()
|
||||
//
|
||||
casChannel::casChannel(const casCtx &ctx) :
|
||||
casPVListChan (ctx)
|
||||
casChannel::casChannel ( const casCtx & ctx ) :
|
||||
pChanI ( new casChannelI ( *this, ctx ) )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::~casChannel()
|
||||
//
|
||||
casChannel::~casChannel()
|
||||
casChannel::~casChannel ()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::getPV()
|
||||
//
|
||||
casPV *casChannel::getPV() // X aCC 361
|
||||
casPV * casChannel::getPV () // X aCC 361
|
||||
{
|
||||
casPVI *pPVI = &this->casChannelI::getPVI();
|
||||
|
||||
if (pPVI!=NULL) {
|
||||
return pPVI->apiPointer();
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
if ( this->pChanI ) {
|
||||
casPVI & pvi = this->pChanI->getPVI ();
|
||||
return pvi.apiPointer ();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::setOwner()
|
||||
//
|
||||
void casChannel::setOwner(const char * const /* pUserName */,
|
||||
const char * const /* pHostName */)
|
||||
{
|
||||
@@ -60,33 +47,21 @@ void casChannel::setOwner(const char * const /* pUserName */,
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::readAccess()
|
||||
//
|
||||
bool casChannel::readAccess () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::writeAccess()
|
||||
//
|
||||
bool casChannel::writeAccess() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::confirmationRequested()
|
||||
//
|
||||
bool casChannel::confirmationRequested() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::show()
|
||||
//
|
||||
void casChannel::show(unsigned level) const
|
||||
{
|
||||
if (level>2u) {
|
||||
@@ -99,19 +74,15 @@ void casChannel::show(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::destroy()
|
||||
//
|
||||
void casChannel::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::postAccessRightsEvent()
|
||||
//
|
||||
void casChannel::postAccessRightsEvent()
|
||||
{
|
||||
this->casChannelI::postAccessRightsEvent();
|
||||
if ( this->pChanI ) {
|
||||
this->pChanI->postAccessRightsEvent ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,188 +15,61 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys inline func
|
||||
#include "casPVIIL.h" // casPVI inline func
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casChannelI.h"
|
||||
#include "casAsyncIOI.h"
|
||||
|
||||
//
|
||||
// casChannelI::casChannelI()
|
||||
//
|
||||
casChannelI::casChannelI ( const casCtx & ctx ) :
|
||||
pClient ( ctx.getClient() ), pPV ( ctx.getPV() ),
|
||||
cid ( ctx.getMsg()->m_cid ), accessRightsEvPending ( false )
|
||||
casChannelI::casChannelI ( casChannel & chanIn, const casCtx & ctx ) :
|
||||
chanForPV ( *ctx.getClient() ), pv ( *ctx.getPV() ),
|
||||
chan ( chanIn ), cid ( ctx.getMsg()->m_cid ),
|
||||
accessRightsEvPending ( false )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::~casChannelI()
|
||||
//
|
||||
casChannelI::~casChannelI()
|
||||
casChannelI::~casChannelI ()
|
||||
{
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLIter<casAsyncIOI> iterAIO = this->ioInProgList.firstIter ();
|
||||
while ( iterAIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIter <casAsyncIOI> tmpAIO = iterAIO;
|
||||
++tmpAIO;
|
||||
iterAIO->serverDestroy ();
|
||||
iterAIO = tmpAIO;
|
||||
}
|
||||
|
||||
//
|
||||
// cancel the monitors
|
||||
//
|
||||
while ( casMonitor * pMon = this->monitorList.get () ) {
|
||||
this->getClient().destroyMonitor ( *pMon );
|
||||
}
|
||||
|
||||
this->pClient->removeChannel ( *this );
|
||||
|
||||
//
|
||||
this->pv.destroyAllIO ( this->ioList );
|
||||
|
||||
// force PV delete if this is the last channel attached
|
||||
//
|
||||
this->pPV->deleteSignal ();
|
||||
this->pv.deleteSignal ();
|
||||
|
||||
delete & this->chan;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::clearOutstandingReads()
|
||||
//
|
||||
void casChannelI::clearOutstandingReads()
|
||||
void casChannelI::uninstallFromPV ( casEventSys & eventSys )
|
||||
{
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLIter <casAsyncIOI> iterIO = this->ioInProgList.firstIter ();
|
||||
while ( iterIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIter<casAsyncIOI> tmp = iterIO;
|
||||
++tmp;
|
||||
iterIO->serverDestroyIfReadOP();
|
||||
iterIO = tmp;
|
||||
tsDLList < casMonitor > dest;
|
||||
this->chanForPV.removeSelfFromPV ( this->pv, dest );
|
||||
while ( casMonitor * pMon = dest.get () ) {
|
||||
eventSys.prepareMonitorForDestroy ( *pMon );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::show()
|
||||
//
|
||||
void casChannelI::show ( unsigned level ) const
|
||||
{
|
||||
printf ( "casChannelI: client id %u PV %s\n",
|
||||
this->cid, this->pPV->getName() );
|
||||
if ( this->monitorList.count() ) {
|
||||
printf ( "List of subscriptions attached\n" );
|
||||
// use the client's lock to protect the list
|
||||
this->pClient->showMonitorsInList (
|
||||
this->monitorList, level );
|
||||
this->cid, this->pv.getName() );
|
||||
if ( level > 0 ) {
|
||||
this->chanForPV.show ( level - 1 );
|
||||
this->chan.show ( level - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::cbFunc()
|
||||
//
|
||||
// access rights event call back
|
||||
//
|
||||
caStatus casChannelI::cbFunc ( casCoreClient & )
|
||||
caStatus casChannelI::cbFunc (
|
||||
casCoreClient &, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
caStatus stat;
|
||||
|
||||
stat = this->pClient->accessRightsResponse ( this );
|
||||
caStatus stat = S_cas_success;
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > guardRelease ( guard );
|
||||
stat = this->chanForPV.client().accessRightsResponse ( this );
|
||||
}
|
||||
if ( stat == S_cas_success ) {
|
||||
this->accessRightsEvPending = false;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
void casChannelI::eventSysDestroyNotify ( casCoreClient & )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::resourceType()
|
||||
//
|
||||
casResType casChannelI::resourceType() const
|
||||
{
|
||||
return casChanT;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::destroy()
|
||||
//
|
||||
// this noop version is safe to be called indirectly
|
||||
// from casChannelI::~casChannelI
|
||||
//
|
||||
void casChannelI::destroy()
|
||||
{
|
||||
}
|
||||
|
||||
void casChannelI::destroyClientNotify ()
|
||||
{
|
||||
casChanDelEv *pCDEV;
|
||||
caStatus status;
|
||||
|
||||
pCDEV = new casChanDelEv ( this->getCID() );
|
||||
if ( pCDEV ) {
|
||||
this->pClient->addToEventQueue ( *pCDEV );
|
||||
}
|
||||
else {
|
||||
status = this->pClient->disconnectChan ( this->getCID () );
|
||||
if ( status ) {
|
||||
//
|
||||
// At this point there is no space in pool
|
||||
// for a tiny object and there is also
|
||||
// no outgoing buffer space in which to place
|
||||
// a message in which we inform the client
|
||||
// that his channel was deleted.
|
||||
//
|
||||
// => disconnect this client via the event
|
||||
// queue because deleting the client here
|
||||
// will result in bugs because no doubt this
|
||||
// could be called by a client member function.
|
||||
//
|
||||
this->pClient->setDestroyPending ();
|
||||
}
|
||||
}
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
bool casChannelI::unistallMonitor ( ca_uint32_t clientIdIn )
|
||||
{
|
||||
//
|
||||
// (it is reasonable to do a linear search here because
|
||||
// sane clients will require only one or two monitors
|
||||
// per channel)
|
||||
//
|
||||
tsDLIter <casMonitor> iter = this->monitorList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
if ( clientIdIn == iter->getClientId () ) {
|
||||
this->monitorList.remove ( *iter.pointer() );
|
||||
this->getClient().destroyMonitor ( *iter.pointer() );
|
||||
return true;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::installMonitor ()
|
||||
//
|
||||
void casChannelI::installMonitor (
|
||||
caResId clientId,
|
||||
const unsigned long count,
|
||||
const unsigned type,
|
||||
const casEventMask & mask )
|
||||
{
|
||||
casMonitor & mon = this->pClient->monitorFactory (
|
||||
*this, clientId, count, type, mask );
|
||||
this->monitorList.add ( mon );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef casChannelIIL_h
|
||||
#define casChannelIIL_h
|
||||
|
||||
#include "casCoreClientIL.h"
|
||||
#include "casEventSysIL.h"
|
||||
|
||||
//
|
||||
// casChannelI::postEvent()
|
||||
//
|
||||
inline void casChannelI::postEvent ( const casEventMask &select, const gdd &event )
|
||||
{
|
||||
this->pClient->postEvent ( this->monitorList, select, event );
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::destroyNoClientNotify()
|
||||
//
|
||||
inline void casChannelI::destroyNoClientNotify()
|
||||
{
|
||||
this->destroy ();
|
||||
}
|
||||
|
||||
#include "casPVIIL.h"
|
||||
|
||||
//
|
||||
// functions that use casPVIIL.h below here
|
||||
//
|
||||
|
||||
//
|
||||
// casChannelI::installAsyncIO()
|
||||
//
|
||||
inline void casChannelI::installAsyncIO ( casAsyncIOI & io )
|
||||
{
|
||||
// install through the client so that we can
|
||||
// use its lock to protect the list
|
||||
this->pClient->installChannelsAsynchIO ( this->ioInProgList, io );
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::removeAsyncIO()
|
||||
//
|
||||
inline void casChannelI::removeAsyncIO ( casAsyncIOI & io )
|
||||
{
|
||||
// uninstall through the client so that we can
|
||||
// use its lock to protect the list
|
||||
this->pClient->uninstallChannelsAsynchIO ( this->ioInProgList, io );
|
||||
this->pPV->unregisterIO ();
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::getSID()
|
||||
// fetch the unsigned integer server id for this PV
|
||||
//
|
||||
inline const caResId casChannelI::getSID()
|
||||
{
|
||||
return this->casRes::getId();
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::postAccessRightsEvent()
|
||||
//
|
||||
inline void casChannelI::postAccessRightsEvent()
|
||||
{
|
||||
if ( ! this->accessRightsEvPending ) {
|
||||
this->accessRightsEvPending = true;
|
||||
this->pClient->addToEventQueue ( *this );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::enumStringTable ()
|
||||
//
|
||||
inline const gddEnumStringTable & casChannelI::enumStringTable () const
|
||||
{
|
||||
return this->pPV->enumStringTable ();
|
||||
}
|
||||
|
||||
#endif // casChannelIIL_h
|
||||
|
||||
@@ -17,16 +17,14 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // inline func for casEventSys
|
||||
#include "casCtxIL.h" // inline func for casCtx
|
||||
#include "inBufIL.h" // inline func for inBuf
|
||||
#include "outBufIL.h" // inline func for outBuf
|
||||
#include "casPVIIL.h" // inline func for casPVI
|
||||
#include "caerr.h"
|
||||
#include "osiWireFormat.h"
|
||||
#include "db_access.h"
|
||||
|
||||
static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u};
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casClient.h"
|
||||
|
||||
static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u};
|
||||
|
||||
//
|
||||
// static declartions for class casClient
|
||||
@@ -51,40 +49,6 @@ casClient::casClient ( caServerI & serverInternal,
|
||||
casClient::loadProtoJumpTable();
|
||||
}
|
||||
|
||||
//
|
||||
// find the channel associated with a resource id
|
||||
//
|
||||
casChannelI * casClient::lookupChannel ( const caResId & idIn )
|
||||
{
|
||||
//
|
||||
// look up the id in a hash table
|
||||
//
|
||||
casChannelI * pChan =
|
||||
this->ctx.getServer()->lookupChannel ( idIn );
|
||||
|
||||
//
|
||||
// update the context
|
||||
//
|
||||
this->ctx.setChannel ( pChan );
|
||||
if ( ! pChan ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// If the channel isnt attached to this client then
|
||||
// something has gone wrong
|
||||
//
|
||||
if ( &pChan->getClient() != this ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// update the context
|
||||
//
|
||||
this->ctx.setPV ( &pChan->getPVI() );
|
||||
return pChan;
|
||||
}
|
||||
|
||||
//
|
||||
// casClient::loadProtoJumpTable()
|
||||
//
|
||||
@@ -258,8 +222,8 @@ caStatus casClient::processMsg ()
|
||||
this->dumpMsg ( & msgTmp, 0,
|
||||
"The client requested transfer is greater than available "
|
||||
"memory in server or EPICS_CA_MAX_ARRAY_BYTES\n" );
|
||||
status = this->sendErr ( & msgTmp, ECA_TOLARGE,
|
||||
"request didnt fit within the CA server's message buffer" );
|
||||
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
|
||||
"client's request didnt fit within the CA server's message buffer" );
|
||||
this->in.removeMsg ( bytesLeft );
|
||||
this->incommingBytesToDrain = msgSize - bytesLeft;
|
||||
}
|
||||
@@ -303,14 +267,14 @@ caStatus casClient::processMsg ()
|
||||
}
|
||||
catch ( std::bad_alloc & ) {
|
||||
status = this->sendErr (
|
||||
this->ctx.getMsg(), ECA_ALLOCMEM,
|
||||
this->ctx.getMsg(), invalidResID, ECA_ALLOCMEM,
|
||||
"inablility to allocate memory in "
|
||||
"the server disconnected client" );
|
||||
status = S_cas_noMemory;
|
||||
}
|
||||
catch ( std::exception & except ) {
|
||||
status = this->sendErr (
|
||||
this->ctx.getMsg(), ECA_INTERNAL,
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
"C++ exception \"%s\" in server "
|
||||
"diconnected client",
|
||||
except.what () );
|
||||
@@ -318,7 +282,7 @@ caStatus casClient::processMsg ()
|
||||
}
|
||||
catch (...) {
|
||||
status = this->sendErr (
|
||||
this->ctx.getMsg(), ECA_INTERNAL,
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
"unexpected C++ exception in server "
|
||||
"diconnected client" );
|
||||
status = S_cas_internal;
|
||||
@@ -420,11 +384,12 @@ void casClient::sendVersion ()
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casClient::sendErr()
|
||||
//
|
||||
caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedStatus,
|
||||
const char *pformat, ... )
|
||||
caStatus casClient::sendErr ( const caHdrLargeArray *curp,
|
||||
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
|
||||
{
|
||||
unsigned stringSize;
|
||||
char msgBuf[1024]; /* allocate plenty of space for the message string */
|
||||
@@ -451,41 +416,6 @@ caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedSta
|
||||
hdrSize += 2 * sizeof ( ca_uint32_t );
|
||||
}
|
||||
|
||||
ca_uint32_t cid = 0u;
|
||||
switch ( curp->m_cmmd ) {
|
||||
case CA_PROTO_SEARCH:
|
||||
cid = curp->m_cid;
|
||||
break;
|
||||
|
||||
case CA_PROTO_EVENT_ADD:
|
||||
case CA_PROTO_EVENT_CANCEL:
|
||||
case CA_PROTO_READ:
|
||||
case CA_PROTO_READ_NOTIFY:
|
||||
case CA_PROTO_WRITE:
|
||||
case CA_PROTO_WRITE_NOTIFY:
|
||||
{
|
||||
/*
|
||||
* Verify the channel
|
||||
*/
|
||||
casChannelI * pciu = this->lookupChannel ( curp->m_cid );
|
||||
if ( pciu ) {
|
||||
cid = pciu->getCID();
|
||||
}
|
||||
else{
|
||||
cid = ~0u;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CA_PROTO_EVENTS_ON:
|
||||
case CA_PROTO_EVENTS_OFF:
|
||||
case CA_PROTO_READ_SYNC:
|
||||
case CA_PROTO_SNAPSHOT:
|
||||
default:
|
||||
cid = (caResId) ~0UL;
|
||||
break;
|
||||
}
|
||||
|
||||
caHdr * pReqOut;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
|
||||
@@ -539,11 +469,11 @@ caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedSta
|
||||
* to a string and send that additional detail
|
||||
*/
|
||||
caStatus casClient::sendErrWithEpicsStatus ( const caHdrLargeArray * pMsg,
|
||||
caStatus epicsStatus, caStatus clientStatus )
|
||||
ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus )
|
||||
{
|
||||
char buf[0x1ff];
|
||||
errSymLookup ( epicsStatus, buf, sizeof(buf) );
|
||||
return this->sendErr ( pMsg, clientStatus, buf );
|
||||
return this->sendErr ( pMsg, cid, clientStatus, buf );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -567,7 +497,7 @@ caStatus casClient::logBadIdWithFileAndLineno ( const caHdrLargeArray * mp,
|
||||
}
|
||||
|
||||
status = this->sendErr (
|
||||
mp, cacStatus, "Bad Resource ID=%u detected at %s.%d",
|
||||
mp, invalidResID, cacStatus, "Bad Resource ID=%u detected at %s.%d",
|
||||
idIn, pFileName, lineno);
|
||||
|
||||
return status;
|
||||
@@ -581,7 +511,7 @@ caStatus casClient::logBadIdWithFileAndLineno ( const caHdrLargeArray * mp,
|
||||
// dp arg allowed to be null
|
||||
//
|
||||
//
|
||||
void casClient::dumpMsg ( const caHdrLargeArray *mp,
|
||||
void casClient::dumpMsg ( const caHdrLargeArray *mp,
|
||||
const void *dp, const char *pFormat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
@@ -593,21 +523,7 @@ void casClient::dumpMsg ( const caHdrLargeArray *mp,
|
||||
}
|
||||
|
||||
char pName[64u];
|
||||
this->hostName (pName, sizeof (pName));
|
||||
|
||||
casChannelI * pciu = this->lookupChannel ( mp->m_cid );
|
||||
|
||||
char pPVName[64u];
|
||||
if (pciu) {
|
||||
strncpy(pPVName, pciu->getPVI().getName(), sizeof(pPVName));
|
||||
if (&pciu->getClient()!=this) {
|
||||
strncat(pPVName, "!Bad Client!", sizeof(pPVName));
|
||||
}
|
||||
pPVName[sizeof(pPVName)-1]='\0';
|
||||
}
|
||||
else {
|
||||
sprintf(pPVName,"%u", mp->m_cid);
|
||||
}
|
||||
this->hostName ( pName, sizeof ( pName ) );
|
||||
|
||||
char pUserName[32];
|
||||
this->userName ( pUserName, sizeof ( pUserName) );
|
||||
@@ -615,12 +531,12 @@ void casClient::dumpMsg ( const caHdrLargeArray *mp,
|
||||
this->hostName ( pHostName, sizeof ( pHostName) );
|
||||
|
||||
fprintf ( stderr,
|
||||
"CAS Request: %s on %s at %s: cmd=%d cid=%s typ=%d cnt=%d psz=%d avail=%x\n",
|
||||
"CAS Request: %s on %s at %s: cmd=%u cid=%u typ=%u cnt=%u psz=%u avail=%x\n",
|
||||
pUserName,
|
||||
pHostName,
|
||||
pName,
|
||||
mp->m_cmmd,
|
||||
pPVName,
|
||||
mp->m_cid,
|
||||
mp->m_dataType,
|
||||
mp->m_count,
|
||||
mp->m_postsize,
|
||||
|
||||
115
src/cas/generic/casClient.h
Normal file
115
src/cas/generic/casClient.h
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef casClienth
|
||||
#define casClienth
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_casClienth
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include "epicsTime.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_casClienth
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "casCoreClient.h"
|
||||
#include "inBuf.h"
|
||||
#include "outBuf.h"
|
||||
|
||||
//
|
||||
// casClient
|
||||
//
|
||||
// this class exists so that udp and tcp can share certain
|
||||
// protocol stubs but is this worth the extra complexity ????
|
||||
//
|
||||
class casClient : public casCoreClient, public outBufClient,
|
||||
public inBufClient {
|
||||
public:
|
||||
casClient ( caServerI &, clientBufMemoryManager &, bufSizeT ioMinSizeIn );
|
||||
virtual ~casClient ();
|
||||
virtual void show ( unsigned level ) const;
|
||||
caStatus sendErr ( const caHdrLargeArray *, ca_uint32_t cid,
|
||||
const int reportedStatus, const char *pFormat, ... );
|
||||
ca_uint16_t protocolRevision() const {return this->minor_version_number;}
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
void sendVersion ();
|
||||
|
||||
protected:
|
||||
inBuf in;
|
||||
outBuf out;
|
||||
ca_uint16_t minor_version_number;
|
||||
unsigned incommingBytesToDrain;
|
||||
epicsTime lastSendTS;
|
||||
epicsTime lastRecvTS;
|
||||
|
||||
caStatus sendErrWithEpicsStatus ( const caHdrLargeArray *pMsg,
|
||||
ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus );
|
||||
|
||||
# define logBadId(MP, DP, CACSTAT, RESID) \
|
||||
this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__, RESID)
|
||||
caStatus logBadIdWithFileAndLineno ( const caHdrLargeArray *mp,
|
||||
const void *dp, const int cacStat, const char *pFileName,
|
||||
const unsigned lineno, const unsigned resId );
|
||||
|
||||
caStatus processMsg();
|
||||
|
||||
//
|
||||
// dump message to stderr
|
||||
//
|
||||
void dumpMsg ( const caHdrLargeArray *mp, const void *dp,
|
||||
const char *pFormat, ... );
|
||||
|
||||
|
||||
private:
|
||||
typedef caStatus ( casClient::*pCASMsgHandler ) ();
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
virtual caStatus uknownMessageAction () = 0;
|
||||
caStatus ignoreMsgAction ();
|
||||
virtual caStatus versionAction ();
|
||||
virtual caStatus eventAddAction ();
|
||||
virtual caStatus eventCancelAction ();
|
||||
virtual caStatus readAction ();
|
||||
virtual caStatus readNotifyAction ();
|
||||
virtual caStatus writeAction ();
|
||||
virtual caStatus searchAction ();
|
||||
virtual caStatus eventsOffAction ();
|
||||
virtual caStatus eventsOnAction ();
|
||||
virtual caStatus readSyncAction ();
|
||||
virtual caStatus clearChannelAction ();
|
||||
virtual caStatus claimChannelAction ();
|
||||
virtual caStatus writeNotifyAction ();
|
||||
virtual caStatus clientNameAction ();
|
||||
virtual caStatus hostNameAction ();
|
||||
virtual caStatus echoAction ();
|
||||
|
||||
virtual void userName ( char * pBuf, unsigned bufSize ) const = 0;
|
||||
|
||||
//
|
||||
// static members
|
||||
//
|
||||
static void loadProtoJumpTable();
|
||||
static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||||
static bool msgHandlersInit;
|
||||
|
||||
casClient ( const casClient & );
|
||||
casClient & operator = ( const casClient & );
|
||||
};
|
||||
|
||||
#endif // casClienth
|
||||
|
||||
@@ -15,57 +15,32 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casCoreClient.h"
|
||||
#include "casAsyncPVExistIOI.h"
|
||||
#include "casAsyncPVAttachIOI.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h"
|
||||
#include "casEventSysIL.h"
|
||||
#include "casCtxIL.h"
|
||||
#include "inBufIL.h"
|
||||
#include "outBufIL.h"
|
||||
#include "casCoreClientIL.h"
|
||||
|
||||
//
|
||||
// casCoreClient::casCoreClient()
|
||||
//
|
||||
casCoreClient::casCoreClient ( caServerI & serverInternal ) :
|
||||
eventSys ( *this )
|
||||
{
|
||||
assert (&serverInternal);
|
||||
ctx.setServer (&serverInternal);
|
||||
ctx.setClient (this);
|
||||
assert ( & serverInternal );
|
||||
ctx.setServer ( & serverInternal );
|
||||
ctx.setClient ( this );
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::~casCoreClient()
|
||||
//
|
||||
casCoreClient::~casCoreClient()
|
||||
{
|
||||
if (this->ctx.getServer()->getDebugLevel()>0u) {
|
||||
errlogPrintf ("CAS: Connection Terminated\n");
|
||||
}
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
tsDLIter<casAsyncIOI> iterIO = this->ioInProgList.firstIter ();
|
||||
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
while ( iterIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIter <casAsyncIOI> tmpIO = iterIO;
|
||||
++tmpIO;
|
||||
iterIO->serverDestroy ();
|
||||
iterIO = tmpIO;
|
||||
// only used by io that does not have a channel
|
||||
while ( casAsyncIOI * pIO = this->ioList.get() ) {
|
||||
pIO->removeFromEventQueue ();
|
||||
delete pIO;
|
||||
}
|
||||
if ( this->ctx.getServer()->getDebugLevel() > 0u ) {
|
||||
errlogPrintf ( "CAS: Connection Terminated\n" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::disconnectChan()
|
||||
//
|
||||
caStatus casCoreClient::disconnectChan(caResId)
|
||||
caStatus casCoreClient::disconnectChan ( caResId )
|
||||
{
|
||||
printf ("Disconnect Chan issued for inappropriate client type?\n");
|
||||
return S_cas_success;
|
||||
@@ -76,7 +51,6 @@ void casCoreClient::show ( unsigned level ) const
|
||||
printf ( "Core client\n" );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.show ( level );
|
||||
printf ( "\t%d io ops in progess\n", this->ioInProgList.count() );
|
||||
this->ctx.show ( level );
|
||||
this->mutex.show ( level );
|
||||
}
|
||||
@@ -95,23 +69,23 @@ caStatus casCoreClient::createChanResponse ( const caHdrLargeArray &, const pvAt
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::readResponse (casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus)
|
||||
caStatus casCoreClient::readResponse ( casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus )
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::readNotifyResponse (casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus)
|
||||
caStatus casCoreClient::readNotifyResponse ( casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus )
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::writeResponse (const caHdrLargeArray &,
|
||||
const caStatus)
|
||||
caStatus casCoreClient::writeResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus )
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::writeNotifyResponse (const caHdrLargeArray &,
|
||||
const caStatus)
|
||||
caStatus casCoreClient::writeNotifyResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus )
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
@@ -135,41 +109,16 @@ caStatus casCoreClient::channelCreateFailedResp ( const caHdrLargeArray &,
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::installChannel()
|
||||
//
|
||||
void casCoreClient::installChannel ( casChannelI & )
|
||||
{
|
||||
assert (0); // dont install channels on the wrong type of client
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::removeChannel()
|
||||
//
|
||||
void casCoreClient::removeChannel ( casChannelI & )
|
||||
{
|
||||
assert (0); // dont install channels on the wrong type of client
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::fetchLastRecvAddr ()
|
||||
//
|
||||
caNetAddr casCoreClient::fetchLastRecvAddr () const
|
||||
{
|
||||
return caNetAddr(); // sets addr type to UDF
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::datagramSequenceNumber ()
|
||||
//
|
||||
ca_uint32_t casCoreClient::datagramSequenceNumber () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::protocolRevision ()
|
||||
//
|
||||
ca_uint16_t casCoreClient::protocolRevision() const
|
||||
{
|
||||
return 0;
|
||||
@@ -197,139 +146,37 @@ casMonitor & casCoreClient::monitorFactory (
|
||||
{
|
||||
casMonitor & mon = this->ctx.getServer()->casMonitorFactory (
|
||||
chan, clientId, count, type, mask, *this );
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.installMonitor ();
|
||||
}
|
||||
this->eventSys.installMonitor ();
|
||||
return mon;
|
||||
}
|
||||
|
||||
void casCoreClient::destroyMonitor ( casMonitor & mon )
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.removeMonitor ();
|
||||
}
|
||||
this->eventSys.removeMonitor ();
|
||||
assert ( mon.numEventsQueued() == 0 );
|
||||
this->ctx.getServer()->casMonitorDestroy ( mon );
|
||||
}
|
||||
|
||||
void casCoreClient::postEvent ( tsDLList < casMonitor > & monitorList,
|
||||
const casEventMask & select, const gdd & event )
|
||||
void casCoreClient::installAsynchIO ( casAsyncPVAttachIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
tsDLIter < casMonitor > iter = monitorList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->postEvent ( this->eventSys, select, event );
|
||||
++iter;
|
||||
}
|
||||
this->ioList.add ( io );
|
||||
}
|
||||
|
||||
void casCoreClient::showMonitorsInList (
|
||||
const tsDLList < casMonitor > & monitorList, unsigned level ) const
|
||||
void casCoreClient::uninstallAsynchIO ( casAsyncPVAttachIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
tsDLIterConst < casMonitor > iter = monitorList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->show ( level );
|
||||
++iter;
|
||||
}
|
||||
this->ioList.remove ( io );
|
||||
}
|
||||
|
||||
void casCoreClient::installChannelsAsynchIO (
|
||||
tsDLList < casAsyncIOI > & list, casAsyncIOI & io )
|
||||
void casCoreClient::installAsynchIO ( casAsyncPVExistIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
list.add ( io );
|
||||
this->ioList.add ( io );
|
||||
}
|
||||
|
||||
void casCoreClient::uninstallChannelsAsynchIO (
|
||||
tsDLList < casAsyncIOI > & list, casAsyncIOI & io )
|
||||
void casCoreClient::uninstallAsynchIO ( casAsyncPVExistIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
list.remove ( io );
|
||||
this->ioList.remove ( io );
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::installAsyncIO()
|
||||
//
|
||||
void casCoreClient::installAsyncIO(casAsyncIOI &ioIn)
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->ioInProgList.add ( ioIn );
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::removeAsyncIO()
|
||||
//
|
||||
void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn)
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->ioInProgList.remove ( ioIn );
|
||||
this->ctx.getServer()->ioBlockedList::signal ();
|
||||
}
|
||||
|
||||
casEventSys::processStatus casCoreClient::eventSysProcess ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
return this->eventSys.process ();
|
||||
}
|
||||
|
||||
void casCoreClient::addToEventQueue ( casEvent & ev )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.addToEventQueue ( ev );
|
||||
}
|
||||
|
||||
// clients lock protects the event list and the
|
||||
// flags in the asynch IO object
|
||||
caStatus casCoreClient::addToEventQueue ( casAsyncIOI & io,
|
||||
bool & onTheQueue, bool & posted )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
// dont allow them to post completion more than once
|
||||
if ( posted || onTheQueue ) {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
posted = true;
|
||||
onTheQueue = true;
|
||||
this->eventSys.addToEventQueue ( io );
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
void casCoreClient::removeFromEventQueue ( casEvent & ev )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.removeFromEventQueue ( ev );
|
||||
}
|
||||
|
||||
void casCoreClient::removeFromEventQueue ( casAsyncIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( io.onTheEventQueue () ) {
|
||||
this->eventSys.removeFromEventQueue ( io );
|
||||
}
|
||||
}
|
||||
|
||||
void casCoreClient::enableEvents ()
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.eventsOn ();
|
||||
}
|
||||
this->eventSignal (); // wake up the event queue consumer
|
||||
}
|
||||
|
||||
void casCoreClient::disableEvents ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.eventsOff ();
|
||||
}
|
||||
|
||||
void casCoreClient::setDestroyPending ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventSys.setDestroyPending ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
227
src/cas/generic/casCoreClient.h
Normal file
227
src/cas/generic/casCoreClient.h
Normal file
@@ -0,0 +1,227 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef casCoreClienth
|
||||
#define casCoreClienth
|
||||
|
||||
#include "caServerI.h"
|
||||
#include "ioBlocked.h"
|
||||
#include "casMonitor.h"
|
||||
#include "casEventSys.h"
|
||||
#include "casCtx.h"
|
||||
|
||||
//
|
||||
// casCoreClient
|
||||
// (this will eventually support direct communication
|
||||
// between the client lib and the server lib)
|
||||
//
|
||||
class casCoreClient : public ioBlocked,
|
||||
private casMonitorCallbackInterface {
|
||||
public:
|
||||
casCoreClient ( caServerI & serverInternal );
|
||||
virtual ~casCoreClient ();
|
||||
virtual caStatus disconnectChan( caResId id );
|
||||
virtual void show ( unsigned level ) const;
|
||||
|
||||
void installAsynchIO ( class casAsyncPVAttachIOI & io );
|
||||
void uninstallAsynchIO ( class casAsyncPVAttachIOI & io );
|
||||
void installAsynchIO ( class casAsyncPVExistIOI & io );
|
||||
void uninstallAsynchIO ( class casAsyncPVExistIOI & io );
|
||||
|
||||
caServerI & getCAS () const;
|
||||
|
||||
//
|
||||
// one virtual function for each CA request type that has
|
||||
// asynchronous completion
|
||||
//
|
||||
virtual caStatus asyncSearchResponse (
|
||||
const caNetAddr & outAddr,
|
||||
const caHdrLargeArray &, const pvExistReturn &,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
|
||||
virtual caStatus createChanResponse (
|
||||
const caHdrLargeArray &, const pvAttachReturn &);
|
||||
virtual caStatus readResponse (
|
||||
casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus );
|
||||
virtual caStatus readNotifyResponse (
|
||||
casChannelI *, const caHdrLargeArray &,
|
||||
const smartConstGDDPointer &, const caStatus );
|
||||
virtual caStatus writeResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus );
|
||||
virtual caStatus writeNotifyResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus );
|
||||
virtual caStatus monitorResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const smartConstGDDPointer &,
|
||||
const caStatus status );
|
||||
virtual caStatus accessRightsResponse ( casChannelI * );
|
||||
virtual caStatus enumPostponedCreateChanResponse (
|
||||
casChannelI &, const caHdrLargeArray &,
|
||||
unsigned dbrType );
|
||||
virtual caStatus channelCreateFailedResp (
|
||||
const caHdrLargeArray &, const caStatus createStatus );
|
||||
|
||||
virtual ca_uint16_t protocolRevision () const = 0;
|
||||
|
||||
// used only with DG clients
|
||||
virtual caNetAddr fetchLastRecvAddr () const;
|
||||
virtual ca_uint32_t datagramSequenceNumber () const;
|
||||
|
||||
bool okToStartAsynchIO ();
|
||||
void setDestroyPending ();
|
||||
|
||||
casEventSys::processStatus eventSysProcess();
|
||||
|
||||
void addToEventQueue ( casMonEvent & );
|
||||
void removeFromEventQueue ( casMonEvent & );
|
||||
caStatus addToEventQueue ( casAsyncIOI &,
|
||||
bool & onTheQueue, bool & posted );
|
||||
void removeFromEventQueue ( casAsyncIOI &,
|
||||
bool & onTheEventQueue );
|
||||
void addToEventQueue (
|
||||
casChannelI &, bool & inTheEventQueue );
|
||||
void enableEvents ();
|
||||
void disableEvents ();
|
||||
caStatus casMonitorCallBack ( casMonitor &,
|
||||
const smartConstGDDPointer & );
|
||||
void postEvent ( tsDLList <casMonitor > &,
|
||||
const casEventMask &select, const gdd &event );
|
||||
|
||||
casMonitor & monitorFactory (
|
||||
casChannelI & ,
|
||||
caResId clientId,
|
||||
const unsigned long count,
|
||||
const unsigned type,
|
||||
const casEventMask & );
|
||||
void destroyMonitor ( casMonitor & mon );
|
||||
|
||||
void casMonEventDestroy (
|
||||
casMonEvent &, epicsGuard < epicsMutex > & );
|
||||
|
||||
protected:
|
||||
mutable epicsMutex mutex;
|
||||
casEventSys eventSys;
|
||||
casCtx ctx;
|
||||
bool userStartedAsyncIO;
|
||||
|
||||
private:
|
||||
// for io that does not have a channel
|
||||
tsDLList < casAsyncIOI > ioList;
|
||||
|
||||
virtual void eventSignal () = 0;
|
||||
|
||||
casCoreClient ( const casCoreClient & );
|
||||
casCoreClient & operator = ( const casCoreClient & );
|
||||
};
|
||||
|
||||
inline caServerI & casCoreClient::getCAS() const
|
||||
{
|
||||
return *this->ctx.getServer();
|
||||
}
|
||||
|
||||
inline bool casCoreClient::okToStartAsynchIO ()
|
||||
{
|
||||
if ( ! this->userStartedAsyncIO ) {
|
||||
this->userStartedAsyncIO = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void casCoreClient::postEvent ( tsDLList < casMonitor > & monitorList,
|
||||
const casEventMask & select, const gdd & event )
|
||||
{
|
||||
bool signalNeeded =
|
||||
this->eventSys.postEvent ( monitorList, select, event );
|
||||
if ( signalNeeded ) {
|
||||
this->eventSignal ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline casEventSys::processStatus casCoreClient::eventSysProcess ()
|
||||
{
|
||||
return this->eventSys.process ();
|
||||
}
|
||||
|
||||
inline caStatus casCoreClient::addToEventQueue ( casAsyncIOI & io,
|
||||
bool & onTheQueue, bool & posted )
|
||||
{
|
||||
bool wakeupNeeded;
|
||||
caStatus status = this->eventSys.addToEventQueue ( io,
|
||||
onTheQueue, posted, wakeupNeeded );
|
||||
if ( wakeupNeeded ) {
|
||||
this->eventSignal ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
inline void casCoreClient::removeFromEventQueue (
|
||||
casAsyncIOI & io, bool & onTheEventQueue )
|
||||
{
|
||||
this->eventSys.removeFromEventQueue ( io, onTheEventQueue );
|
||||
}
|
||||
|
||||
inline void casCoreClient::addToEventQueue ( casMonEvent & ev )
|
||||
{
|
||||
this->eventSys.addToEventQueue ( ev );
|
||||
}
|
||||
|
||||
inline void casCoreClient::removeFromEventQueue ( casMonEvent & ev )
|
||||
{
|
||||
this->eventSys.removeFromEventQueue ( ev );
|
||||
}
|
||||
|
||||
inline void casCoreClient::addToEventQueue (
|
||||
casChannelI & ev, bool & inTheEventQueue )
|
||||
{
|
||||
bool signalNeeded =
|
||||
this->eventSys.addToEventQueue ( ev, inTheEventQueue );
|
||||
if ( signalNeeded ) {
|
||||
this->eventSignal ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void casCoreClient::enableEvents ()
|
||||
{
|
||||
this->eventSys.eventsOn ();
|
||||
this->eventSignal (); // wake up the event queue consumer
|
||||
}
|
||||
|
||||
inline void casCoreClient::disableEvents ()
|
||||
{
|
||||
bool signalNeeded =
|
||||
this->eventSys.eventsOff ();
|
||||
if ( signalNeeded ) {
|
||||
this->eventSignal ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void casCoreClient::setDestroyPending ()
|
||||
{
|
||||
this->eventSys.setDestroyPending ();
|
||||
this->eventSignal ();
|
||||
}
|
||||
|
||||
inline void casCoreClient::casMonEventDestroy (
|
||||
casMonEvent & ev, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->eventSys.casMonEventDestroy ( ev, guard );
|
||||
}
|
||||
|
||||
#endif // casCoreClienth
|
||||
|
||||
@@ -8,12 +8,20 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include "server.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//
|
||||
// casCtx::show()
|
||||
//
|
||||
void casCtx::show (unsigned level) const
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casCtx.h"
|
||||
|
||||
casCtx::casCtx() :
|
||||
pData(NULL), pCAS(NULL), pClient(NULL),
|
||||
pChannel(NULL), pPV(NULL), nAsyncIO(0u)
|
||||
{
|
||||
memset(&this->msg, 0, sizeof(this->msg));
|
||||
}
|
||||
|
||||
void casCtx::show ( unsigned level ) const
|
||||
{
|
||||
printf ( "casCtx at %p\n",
|
||||
static_cast <const void *> ( this ) );
|
||||
|
||||
@@ -14,20 +14,15 @@
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "gddApps.h"
|
||||
#include "caerr.h"
|
||||
#include "osiWireFormat.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI inline func
|
||||
#include "inBufIL.h" // inline functions for inBuf
|
||||
#include "outBufIL.h" // inline func for outBuf
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
#include "casCoreClientIL.h" // casCoreClient inline func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casDGClient.h"
|
||||
#include "osiPoolStatus.h" // osi pool monitoring functions
|
||||
|
||||
//
|
||||
// CA Server Datagram (DG) Client
|
||||
//
|
||||
|
||||
//
|
||||
// casDGClient::casDGClient()
|
||||
//
|
||||
@@ -130,24 +125,24 @@ caStatus casDGClient::searchAction()
|
||||
// search requests, and therefore dont thrash through
|
||||
// caServer::pvExistTest() and casCreatePV::pvAttach()
|
||||
//
|
||||
if (!osiSufficentSpaceInPool(0)) {
|
||||
if ( ! osiSufficentSpaceInPool ( 0 ) ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// ask the server tool if this PV exists
|
||||
//
|
||||
this->asyncIOFlag = false;
|
||||
this->userStartedAsyncIO = false;
|
||||
pvExistReturn pver =
|
||||
this->getCAS()->pvExistTest(this->ctx, pChanName);
|
||||
this->getCAS()->pvExistTest ( this->ctx, pChanName );
|
||||
|
||||
//
|
||||
// prevent problems when they initiate
|
||||
// async IO but dont return status
|
||||
// indicating so (and vise versa)
|
||||
//
|
||||
if ( this->asyncIOFlag ) {
|
||||
if (pver.getStatus()!=pverAsyncCompletion) {
|
||||
if ( this->userStartedAsyncIO ) {
|
||||
if ( pver.getStatus() != pverAsyncCompletion ) {
|
||||
errMessage (S_cas_badParameter,
|
||||
"- assuming asynch IO status from caServer::pvExistTest()");
|
||||
}
|
||||
@@ -157,7 +152,7 @@ caStatus casDGClient::searchAction()
|
||||
//
|
||||
// otherwise we assume sync IO operation was initiated
|
||||
//
|
||||
switch (pver.getStatus()) {
|
||||
switch ( pver.getStatus() ) {
|
||||
case pverExistsHere:
|
||||
status = this->searchResponse (*mp, pver);
|
||||
break;
|
||||
@@ -213,8 +208,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
// new API was added to the server (they must
|
||||
// now use clients at EPICS 3.12 or higher)
|
||||
//
|
||||
status = this->sendErr(&msg, ECA_DEFUNCT,
|
||||
"R3.11 connect sequence from old client was ignored");
|
||||
status = this->sendErr ( &msg, ECA_DEFUNCT, invalidResID,
|
||||
"R3.11 connect sequence from old client was ignored" );
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -457,10 +452,6 @@ caStatus casDGClient::asyncSearchResponse ( const caNetAddr & outAddr,
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
//
|
||||
// start a DG context in the output protocol stream
|
||||
// and grab the send lock
|
||||
//
|
||||
void * pRaw;
|
||||
const outBufCtx outctx = this->out.pushCtx
|
||||
( sizeof(cadg), MAX_UDP_SEND, pRaw );
|
||||
|
||||
98
src/cas/generic/casDGClient.h
Normal file
98
src/cas/generic/casDGClient.h
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef casDGClienth
|
||||
#define casDGClienth
|
||||
|
||||
#include "casClient.h"
|
||||
|
||||
class casDGClient : public casClient {
|
||||
public:
|
||||
casDGClient ( class caServerI & serverIn,
|
||||
clientBufMemoryManager & );
|
||||
virtual ~casDGClient ();
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
|
||||
void sendBeacon ( ca_uint32_t beaconNumber );
|
||||
|
||||
virtual void sendBeaconIO ( char &msg, bufSizeT length,
|
||||
aitUint16 &portField, aitUint32 &addrField ) = 0;
|
||||
|
||||
void destroy ();
|
||||
|
||||
unsigned getDebugLevel () const;
|
||||
|
||||
void hostName ( char * pBuf, unsigned bufSize ) const;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
|
||||
caNetAddr fetchLastRecvAddr () const;
|
||||
|
||||
virtual caNetAddr serverAddress () const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
caStatus processDG ();
|
||||
|
||||
private:
|
||||
caNetAddr lastRecvAddr;
|
||||
ca_uint32_t seqNoOfReq;
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
caStatus searchAction ();
|
||||
caStatus uknownMessageAction ();
|
||||
|
||||
//
|
||||
// searchFailResponse()
|
||||
//
|
||||
caStatus searchFailResponse ( const caHdrLargeArray *pMsg );
|
||||
|
||||
caStatus searchResponse ( const caHdrLargeArray &,
|
||||
const pvExistReturn & retVal );
|
||||
|
||||
caStatus asyncSearchResponse ( const caNetAddr & outAddr,
|
||||
const caHdrLargeArray & msg, const pvExistReturn & retVal,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
|
||||
|
||||
//
|
||||
// IO depen
|
||||
//
|
||||
outBufClient::flushCondition xSend ( char *pBufIn, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent );
|
||||
inBufClient::fillCondition xRecv ( char *pBufIn, bufSizeT nBytesToRecv,
|
||||
fillParameter parm, bufSizeT &nByesRecv );
|
||||
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
const caNetAddr & addr ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
fillParameter parm, bufSizeT &nBytesActual, caNetAddr & addr ) = 0;
|
||||
|
||||
caStatus versionAction ();
|
||||
|
||||
ca_uint32_t datagramSequenceNumber () const;
|
||||
|
||||
//
|
||||
// cadg
|
||||
//
|
||||
struct cadg {
|
||||
caNetAddr cadg_addr; // invalid address indicates pad
|
||||
bufSizeT cadg_nBytes;
|
||||
};
|
||||
|
||||
casDGClient ( const casDGClient & );
|
||||
casDGClient & operator = ( const casDGClient & );
|
||||
};
|
||||
|
||||
#endif // casDGClienth
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "casEventRegistry.h"
|
||||
|
||||
#ifdef TEST
|
||||
main ()
|
||||
@@ -63,117 +65,88 @@ main ()
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// casEventRegistry::maskAllocator()
|
||||
//
|
||||
casEventMask casEventRegistry::maskAllocator()
|
||||
casEventMask casEventRegistry::maskAllocator ()
|
||||
{
|
||||
casEventMask evMask;
|
||||
|
||||
if (this->maskBitAllocator<CHAR_BIT*sizeof(evMask.mask)) {
|
||||
evMask.mask = 1u<<(this->maskBitAllocator++);
|
||||
if ( this->maskBitAllocator < CHAR_BIT * sizeof ( evMask.mask ) ) {
|
||||
evMask.mask = 1u << ( this->maskBitAllocator++ );
|
||||
}
|
||||
return evMask;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventRegistry::registerEvent()
|
||||
//
|
||||
casEventMask casEventRegistry::registerEvent(const char *pName)
|
||||
casEventMask casEventRegistry::registerEvent ( const char *pName )
|
||||
{
|
||||
//
|
||||
// NOTE: pName outlives id here
|
||||
// (so the refString option is ok)
|
||||
//
|
||||
stringId id (pName, stringId::refString);
|
||||
casEventMaskEntry *pEntry;
|
||||
casEventMask mask;
|
||||
stringId id ( pName, stringId::refString );
|
||||
casEventMaskEntry * pEntry;
|
||||
casEventMask mask;
|
||||
|
||||
pEntry = this->lookup (id);
|
||||
pEntry = this->lookup ( id );
|
||||
if (pEntry) {
|
||||
mask = *pEntry;
|
||||
}
|
||||
else {
|
||||
mask = this->maskAllocator();
|
||||
if (mask.mask == 0u) {
|
||||
errMessage (S_cas_tooManyEvents, NULL);
|
||||
mask = this->maskAllocator ();
|
||||
if ( mask.mask == 0u ) {
|
||||
errMessage ( S_cas_tooManyEvents, NULL );
|
||||
}
|
||||
else {
|
||||
pEntry = new casEventMaskEntry(*this, mask, pName);
|
||||
pEntry = new casEventMaskEntry ( *this, mask, pName );
|
||||
mask = *pEntry;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMask::show()
|
||||
//
|
||||
void casEventMask::show(unsigned level) const
|
||||
void casEventMask::show ( unsigned level ) const
|
||||
{
|
||||
if (level>0u) {
|
||||
printf ("casEventMask = %x\n", this->mask);
|
||||
if ( level > 0u ) {
|
||||
printf ( "casEventMask = %x\n", this->mask );
|
||||
}
|
||||
}
|
||||
|
||||
casEventMask::casEventMask (casEventRegistry ®, const char *pName)
|
||||
casEventMask::casEventMask ( casEventRegistry & reg, const char * pName )
|
||||
{
|
||||
*this = reg.registerEvent (pName);
|
||||
*this = reg.registerEvent ( pName );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventRegistry::show()
|
||||
//
|
||||
void casEventRegistry::show(unsigned level) const
|
||||
void casEventRegistry::show ( unsigned level ) const
|
||||
{
|
||||
if (level>1u) {
|
||||
if ( level > 1u ) {
|
||||
printf ("casEventRegistry: bit allocator = %d\n",
|
||||
this->maskBitAllocator);
|
||||
}
|
||||
this->resTable <casEventMaskEntry, stringId>::show(level);
|
||||
this->resTable < casEventMaskEntry, stringId >::show ( level );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::casEventMaskEntry()
|
||||
//
|
||||
casEventMaskEntry::casEventMaskEntry(
|
||||
casEventRegistry ®In, casEventMask maskIn, const char *pName) :
|
||||
casEventMask (maskIn), stringId (pName), reg (regIn)
|
||||
casEventMaskEntry::casEventMaskEntry (
|
||||
casEventRegistry & regIn, casEventMask maskIn, const char * pName ) :
|
||||
casEventMask ( maskIn ), stringId ( pName ), reg ( regIn )
|
||||
{
|
||||
int stat;
|
||||
|
||||
assert (this->resourceName()!=NULL);
|
||||
stat = this->reg.add(*this);
|
||||
assert (stat==0);
|
||||
assert ( this->resourceName() != NULL );
|
||||
stat = this->reg.add ( *this );
|
||||
assert ( stat == 0 );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::~casEventMaskEntry()
|
||||
//
|
||||
// empty destructor forces virtual
|
||||
//
|
||||
// (not inline so that we avoid duplication resulting
|
||||
// in the object code created by some compilers)
|
||||
//
|
||||
casEventMaskEntry::~casEventMaskEntry()
|
||||
{
|
||||
this->reg.remove (*this);
|
||||
this->reg.remove ( *this );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::destroy()
|
||||
//
|
||||
void casEventMaskEntry::destroy()
|
||||
void casEventMaskEntry::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::show()
|
||||
//
|
||||
void casEventMaskEntry::show (unsigned level) const
|
||||
void casEventMaskEntry::show ( unsigned level ) const
|
||||
{
|
||||
this->casEventMask::show(level);
|
||||
this->stringId::show(level);
|
||||
this->casEventMask::show ( level );
|
||||
this->stringId::show ( level );
|
||||
}
|
||||
|
||||
|
||||
@@ -47,26 +47,26 @@ public:
|
||||
this->mask = 0u;
|
||||
}
|
||||
|
||||
casEventMask (casEventRegistry ®, const char *pName);
|
||||
casEventMask ( casEventRegistry ®, const char *pName );
|
||||
|
||||
casEventMask ()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void show (unsigned level) const;
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
int eventsSelected()
|
||||
bool eventsSelected () const
|
||||
{
|
||||
return this->mask!=0u;
|
||||
return this->mask != 0u;
|
||||
}
|
||||
int noEventsSelected()
|
||||
bool noEventsSelected () const
|
||||
{
|
||||
return this->mask==0u;
|
||||
return this->mask == 0u;
|
||||
}
|
||||
|
||||
inline void operator|= (const casEventMask &rhs);
|
||||
inline void operator&= (const casEventMask &rhs);
|
||||
inline void operator |= ( const casEventMask & rhs );
|
||||
inline void operator &= ( const casEventMask & rhs );
|
||||
|
||||
private:
|
||||
unsigned mask;
|
||||
|
||||
@@ -15,38 +15,30 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
/*
|
||||
* ANSI C
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* EPICS
|
||||
*/
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casMonitor inline func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caHdrLargeArray.h"
|
||||
#include "casCoreClient.h"
|
||||
#include "casAsyncIOI.h"
|
||||
#include "casChannelI.h"
|
||||
|
||||
//
|
||||
// casEventSys::show()
|
||||
//
|
||||
void casEventSys::show(unsigned level) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
printf ( "casEventSys at %p\n",
|
||||
static_cast <const void *> ( this ) );
|
||||
if (level>=1u) {
|
||||
printf ("\tnumEventBlocks = %u, maxLogEntries = %u\n",
|
||||
this->numEventBlocks, this->maxLogEntries);
|
||||
printf ("\tthere are %d events in the queue\n",
|
||||
this->eventLogQue.count());
|
||||
printf ("Replace events flag = %d, dontProcess flag = %d\n",
|
||||
printf ( "\numSubscriptions = %u, maxLogEntries = %u\n",
|
||||
this->numSubscriptions, this->maxLogEntries );
|
||||
printf ( "\tthere are %d events in the queue\n",
|
||||
this->eventLogQue.count() );
|
||||
printf ( "Replace events flag = %d, dontProcess flag = %d\n",
|
||||
static_cast < int > ( this->replaceEvents ),
|
||||
static_cast < int > ( this->dontProcess ) );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::~casEventSys()
|
||||
//
|
||||
casEventSys::~casEventSys()
|
||||
{
|
||||
if ( this->pPurgeEvent != NULL ) {
|
||||
@@ -54,44 +46,53 @@ casEventSys::~casEventSys()
|
||||
delete this->pPurgeEvent;
|
||||
}
|
||||
|
||||
/*
|
||||
* all active event blocks must be canceled first
|
||||
*/
|
||||
casVerify ( this->numEventBlocks == 0 );
|
||||
// at this point:
|
||||
// o all channels delete
|
||||
// o all IO deleted
|
||||
// o any subscription events remaining on the queue
|
||||
// are pending destroy
|
||||
|
||||
while ( casEvent * pE = this->eventLogQue.get () ) {
|
||||
pE->eventSysDestroyNotify ( this->client );
|
||||
}
|
||||
// this will clean up the event queue because all
|
||||
// channels have been deleted and any events left on
|
||||
// the queue are there because they are going to
|
||||
// execute a subscription delete
|
||||
this->process ();
|
||||
|
||||
// verify above assertion is true
|
||||
casVerify ( this->eventLogQue.count() == 0 );
|
||||
|
||||
// all active subscriptions should also have been
|
||||
// uninstalled
|
||||
casVerify ( this->numSubscriptions == 0 );
|
||||
if ( this->numSubscriptions != 0 ) {
|
||||
printf ( "numSubscriptions=%u\n", this->numSubscriptions );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::installMonitor()
|
||||
//
|
||||
void casEventSys::installMonitor()
|
||||
void casEventSys::installMonitor ()
|
||||
{
|
||||
this->numEventBlocks++;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
assert ( this->numSubscriptions < UINT_MAX );
|
||||
this->numSubscriptions++;
|
||||
this->maxLogEntries += averageEventEntries;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::removeMonitor ()
|
||||
//
|
||||
void casEventSys::removeMonitor ()
|
||||
{
|
||||
assert (this->numEventBlocks>=1u);
|
||||
this->numEventBlocks--;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
assert ( this->numSubscriptions >= 1u );
|
||||
this->numSubscriptions--;
|
||||
this->maxLogEntries -= averageEventEntries;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::process()
|
||||
//
|
||||
casEventSys::processStatus casEventSys::process ()
|
||||
{
|
||||
casEventSys::processStatus ps;
|
||||
ps.cond = casProcOk;
|
||||
ps.nAccepted = 0u;
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
while ( ! this->dontProcess ) {
|
||||
casEvent * pEvent;
|
||||
|
||||
@@ -101,14 +102,15 @@ casEventSys::processStatus casEventSys::process ()
|
||||
break;
|
||||
}
|
||||
|
||||
caStatus status = pEvent->cbFunc ( this->client );
|
||||
caStatus status = pEvent->cbFunc (
|
||||
this->client, guard );
|
||||
if ( status == S_cas_success ) {
|
||||
ps.nAccepted++;
|
||||
}
|
||||
else if ( status == S_cas_sendBlocked ) {
|
||||
// not accepted so return to the head of the list
|
||||
// (we will try again later)
|
||||
this->pushOnToEventQueue ( *pEvent );
|
||||
this->eventLogQue.push ( *pEvent );
|
||||
ps.cond = casProcOk;
|
||||
break;
|
||||
}
|
||||
@@ -140,11 +142,10 @@ casEventSys::processStatus casEventSys::process ()
|
||||
return ps;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::eventsOn()
|
||||
//
|
||||
void casEventSys::eventsOn()
|
||||
void casEventSys::eventsOn ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
//
|
||||
// allow multiple events for each monitor
|
||||
//
|
||||
@@ -165,62 +166,188 @@ void casEventSys::eventsOn()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::eventsOff()
|
||||
//
|
||||
void casEventSys::eventsOff()
|
||||
bool casEventSys::eventsOff ()
|
||||
{
|
||||
//
|
||||
// new events will replace the last event on
|
||||
// the queue for a particular monitor
|
||||
//
|
||||
this->replaceEvents = true;
|
||||
bool signalNeeded = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
//
|
||||
// suppress the processing and sending of events
|
||||
// only after we have purged the event queue
|
||||
// for this particular client
|
||||
//
|
||||
if ( this->pPurgeEvent == NULL ) {
|
||||
this->pPurgeEvent = new casEventPurgeEv ( *this );
|
||||
if ( this->pPurgeEvent == NULL ) {
|
||||
//
|
||||
// if there is no room for the event then immediately
|
||||
// stop processing and sending events to the client
|
||||
// until we exit flow control
|
||||
//
|
||||
this->dontProcess = true;
|
||||
}
|
||||
else {
|
||||
this->casEventSys::addToEventQueue ( *this->pPurgeEvent );
|
||||
}
|
||||
}
|
||||
//
|
||||
// new events will replace the last event on
|
||||
// the queue for a particular monitor
|
||||
//
|
||||
this->replaceEvents = true;
|
||||
|
||||
//
|
||||
// suppress the processing and sending of events
|
||||
// only after we have purged the event queue
|
||||
// for this particular client
|
||||
//
|
||||
if ( this->pPurgeEvent == NULL ) {
|
||||
this->pPurgeEvent = new casEventPurgeEv ( *this );
|
||||
if ( this->pPurgeEvent == NULL ) {
|
||||
//
|
||||
// if there is no room for the event then immediately
|
||||
// stop processing and sending events to the client
|
||||
// until we exit flow control
|
||||
//
|
||||
this->dontProcess = true;
|
||||
}
|
||||
else {
|
||||
if ( this->eventLogQue.count() == 0 ) {
|
||||
signalNeeded = true;
|
||||
}
|
||||
this->eventLogQue.add ( *this->pPurgeEvent );
|
||||
signalNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return signalNeeded;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventPurgeEv::casEventPurgeEv ()
|
||||
//
|
||||
casEventPurgeEv::casEventPurgeEv ( casEventSys & evSysIn ) :
|
||||
evSys ( evSysIn )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casEventPurgeEv::cbFunc()
|
||||
//
|
||||
caStatus casEventPurgeEv::cbFunc ( casCoreClient & )
|
||||
caStatus casEventPurgeEv::cbFunc ( casCoreClient &, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->evSys.dontProcess = true;
|
||||
this->evSys.pPurgeEvent = NULL;
|
||||
|
||||
delete this;
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unklocker ( guard );
|
||||
delete this;
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
void casEventPurgeEv::eventSysDestroyNotify ( casCoreClient & )
|
||||
caStatus casEventSys::addToEventQueue ( casAsyncIOI & event,
|
||||
bool & onTheQueue, bool & posted, bool & wakeupNeeded )
|
||||
{
|
||||
delete this;
|
||||
wakeupNeeded = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
// dont allow them to post completion more than once
|
||||
if ( posted || onTheQueue ) {
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
posted = true;
|
||||
onTheQueue = true;
|
||||
wakeupNeeded = ! this->dontProcess && this->eventLogQue.count() == 0;
|
||||
this->eventLogQue.add ( event );
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
bool casEventSys::addToEventQueue ( casChannelI & event, bool & inTheEventQueue )
|
||||
{
|
||||
bool wakeupRequired = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( ! inTheEventQueue ) {
|
||||
inTheEventQueue = true;
|
||||
wakeupRequired = ! this->dontProcess && this->eventLogQue.count()==0;
|
||||
this->eventLogQue.add ( event );
|
||||
}
|
||||
}
|
||||
return wakeupRequired;
|
||||
}
|
||||
|
||||
void casEventSys::removeFromEventQueue ( casMonEvent & event )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->eventLogQue.remove ( event );
|
||||
}
|
||||
|
||||
void casEventSys::removeFromEventQueue ( casAsyncIOI & io, bool & onTheEventQueue )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( onTheEventQueue ) {
|
||||
onTheEventQueue = false;
|
||||
this->eventLogQue.remove ( io );
|
||||
}
|
||||
}
|
||||
|
||||
void casEventSys::setDestroyPending ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->destroyPending = true;
|
||||
}
|
||||
|
||||
inline bool casEventSys::full () const // X aCC 361
|
||||
{
|
||||
if ( this->replaceEvents || this->eventLogQue.count() >= this->maxLogEntries ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool casEventSys::postEvent ( tsDLList < casMonitor > & monitorList,
|
||||
const casEventMask & select, const gdd & event )
|
||||
{
|
||||
bool signalNeeded = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
tsDLIter < casMonitor > iter = monitorList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
if ( iter->selected ( select ) ) {
|
||||
// get a new block if we havent exceeded quotas
|
||||
bool full = ( iter->numEventsQueued() >= individualEventEntries )
|
||||
|| this->full ();
|
||||
casMonEvent * pLog;
|
||||
if ( ! full ) {
|
||||
// should I get rid of this try block by implementing a no
|
||||
// throw version of the free list alloc? However, crude
|
||||
// tests on windows with ms visual C++ dont appear to argue
|
||||
// against the try block.
|
||||
try {
|
||||
pLog = new ( this->casMonEventFreeList )
|
||||
casMonEvent ( *iter, event );
|
||||
}
|
||||
catch ( ... ) {
|
||||
pLog = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pLog = 0;
|
||||
}
|
||||
|
||||
if ( this->eventLogQue.count() == 0 ) {
|
||||
signalNeeded = true;
|
||||
}
|
||||
iter->installNewEventLog ( this->eventLogQue, pLog, event );
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
return signalNeeded;
|
||||
}
|
||||
|
||||
void casEventSys::casMonEventDestroy (
|
||||
casMonEvent & ev, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
ev.~casMonEvent ();
|
||||
this->casMonEventFreeList.release ( & ev );
|
||||
}
|
||||
|
||||
void casEventSys::prepareMonitorForDestroy ( casMonitor & mon )
|
||||
{
|
||||
bool safeToDestroy = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
mon.markDestroyPending ();
|
||||
// if events reference it on the queue then it gets
|
||||
// deleted when it reaches the top of the queue
|
||||
if ( mon.numEventsQueued () == 0 ) {
|
||||
safeToDestroy = true;
|
||||
}
|
||||
}
|
||||
if ( safeToDestroy ) {
|
||||
this->client.destroyMonitor ( mon );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef casEventSysIL_h
|
||||
#define casEventSysIL_h
|
||||
|
||||
//
|
||||
// casEventSys::casEventSys ()
|
||||
//
|
||||
inline casEventSys::casEventSys ( casCoreClient & clientIn ) :
|
||||
client ( clientIn ),
|
||||
pPurgeEvent ( NULL ),
|
||||
numEventBlocks ( 0u ),
|
||||
maxLogEntries ( individualEventEntries ),
|
||||
destroyPending ( false ),
|
||||
replaceEvents ( false ),
|
||||
dontProcess ( false )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::addToEventQueue()
|
||||
//
|
||||
inline void casEventSys::addToEventQueue ( casEvent & event )
|
||||
{
|
||||
this->eventLogQue.add ( event );
|
||||
|
||||
//
|
||||
// wake up the event queue consumer only if
|
||||
// we are not supressing events to a client that
|
||||
// is in flow control
|
||||
//
|
||||
if ( ! this->dontProcess ) {
|
||||
this->client.eventSignal ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::setDestroyPending()
|
||||
//
|
||||
inline void casEventSys::setDestroyPending()
|
||||
{
|
||||
this->destroyPending = true;
|
||||
//
|
||||
// wakes up the event queue consumer
|
||||
//
|
||||
this->client.eventSignal ();
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::insertEventQueue()
|
||||
//
|
||||
inline void casEventSys::insertEventQueue( casEvent & insert, casEvent & prevEvent )
|
||||
{
|
||||
this->eventLogQue.insertAfter ( insert, prevEvent );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::pushOnToEventQueue()
|
||||
//
|
||||
inline void casEventSys::pushOnToEventQueue ( casEvent & event )
|
||||
{
|
||||
this->eventLogQue.push ( event );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::removeFromEventQueue()
|
||||
//
|
||||
inline void casEventSys::removeFromEventQueue ( casEvent & event )
|
||||
{
|
||||
this->eventLogQue.remove ( event );
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::full()
|
||||
//
|
||||
inline bool casEventSys::full() // X aCC 361
|
||||
{
|
||||
if ( this->replaceEvents || this->eventLogQue.count() >= this->maxLogEntries ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // casEventSysIL_h
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#include "cxxCompilerDependencies.h"
|
||||
#include "tsDLList.h"
|
||||
#include "tsFreeList.h"
|
||||
#include "resourceLib.h"
|
||||
#define CA_MINOR_PROTOCOL_REVISION 11
|
||||
#include "caProto.h"
|
||||
#include "smartGDDPointer.h"
|
||||
|
||||
typedef aitUint32 caResId;
|
||||
|
||||
class casChannelI;
|
||||
class casCoreClient;
|
||||
|
||||
//
|
||||
// casEvent
|
||||
//
|
||||
class casEvent : public tsDLNode < casEvent > {
|
||||
public:
|
||||
virtual caStatus cbFunc ( casCoreClient & ) = 0;
|
||||
virtual void eventSysDestroyNotify ( casCoreClient & ) = 0;
|
||||
protected:
|
||||
epicsShareFunc virtual ~casEvent();
|
||||
};
|
||||
|
||||
class casChanDelEv : public casEvent {
|
||||
public:
|
||||
casChanDelEv ( caResId idIn ) : id(idIn) {}
|
||||
~casChanDelEv ();
|
||||
private:
|
||||
caResId id;
|
||||
caStatus cbFunc ( casCoreClient & );
|
||||
void eventSysDestroyNotify ( casCoreClient & );
|
||||
};
|
||||
|
||||
enum casResType {casChanT=1, casMonitorT, casPVT};
|
||||
|
||||
class casRes : public chronIntIdRes<casRes>
|
||||
{
|
||||
public:
|
||||
casRes ();
|
||||
epicsShareFunc virtual ~casRes();
|
||||
virtual casResType resourceType () const = 0;
|
||||
virtual void show ( unsigned level ) const = 0;
|
||||
//virtual void destroy() = 0;
|
||||
private:
|
||||
casRes ( const casRes & );
|
||||
casRes & operator = ( const casRes & );
|
||||
};
|
||||
|
||||
class ioBlockedList;
|
||||
class epicsMutex;
|
||||
|
||||
//
|
||||
// ioBlocked
|
||||
//
|
||||
class ioBlocked : public tsDLNode<ioBlocked> {
|
||||
friend class ioBlockedList;
|
||||
public:
|
||||
ioBlocked ();
|
||||
virtual ~ioBlocked ();
|
||||
private:
|
||||
ioBlockedList * pList;
|
||||
virtual void ioBlockedSignal ();
|
||||
};
|
||||
|
||||
//
|
||||
// ioBlockedList
|
||||
//
|
||||
class ioBlockedList : private tsDLList<ioBlocked> {
|
||||
friend class ioBlocked;
|
||||
public:
|
||||
ioBlockedList ();
|
||||
epicsShareFunc virtual ~ioBlockedList ();
|
||||
void signal ();
|
||||
void addItemToIOBLockedList (ioBlocked &item);
|
||||
ioBlockedList ( const ioBlockedList & );
|
||||
ioBlockedList & operator = ( const ioBlockedList & );
|
||||
};
|
||||
|
||||
class casMonitor;
|
||||
|
||||
//
|
||||
// casMonEvent
|
||||
//
|
||||
class casMonEvent : public casEvent {
|
||||
public:
|
||||
casMonEvent ();
|
||||
casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue);
|
||||
casMonEvent (const casMonEvent &initValue);
|
||||
~casMonEvent ();
|
||||
smartConstGDDPointer getValue () const;
|
||||
void operator = (const class casMonEvent &monEventIn);
|
||||
void clear ();
|
||||
void assign (casMonitor &monitor, const smartConstGDDPointer &pValueIn);
|
||||
void * operator new ( size_t size, tsFreeList < class casMonEvent, 1024 > & );
|
||||
epicsPlacementDeleteOperator (( void *, tsFreeList < class casMonEvent, 1024 > & ))
|
||||
private:
|
||||
smartConstGDDPointer pValue;
|
||||
caResId id;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
caStatus cbFunc ( casCoreClient & );
|
||||
void eventSysDestroyNotify ( casCoreClient & );
|
||||
};
|
||||
|
||||
class casMonitorCallbackInterface { // X aCC 655
|
||||
public:
|
||||
virtual caStatus casMonitorCallBack ( casMonitor &,
|
||||
const smartConstGDDPointer & pValue ) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// casMonitor()
|
||||
//
|
||||
class casMonitor :
|
||||
public tsDLNode < casMonitor >, public casRes {
|
||||
public:
|
||||
casMonitor ( caResId clientIdIn, casChannelI & chan,
|
||||
unsigned long nElem, unsigned dbrType,
|
||||
const casEventMask & maskIn,
|
||||
casMonitorCallbackInterface & );
|
||||
virtual ~casMonitor();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
caStatus executeEvent ( casMonEvent & );
|
||||
|
||||
void postEvent ( class casEventSys & evSys,
|
||||
const casEventMask & select,
|
||||
const smartConstGDDPointer & pValue );
|
||||
|
||||
caResId getClientId () const
|
||||
{
|
||||
return this->clientId;
|
||||
}
|
||||
|
||||
unsigned getType () const
|
||||
{
|
||||
return this->dbrType;
|
||||
}
|
||||
|
||||
unsigned long getCount () const
|
||||
{
|
||||
return this->nElem;
|
||||
}
|
||||
casChannelI & getChannel () const
|
||||
{
|
||||
return this->ciu;
|
||||
}
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < casMonitor, 1024 > & )
|
||||
epicsThrows ( (std::bad_alloc) );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < casMonitor, 1024 > & ))
|
||||
|
||||
private:
|
||||
casMonEvent overFlowEvent;
|
||||
unsigned long const nElem;
|
||||
casChannelI & ciu;
|
||||
casMonitorCallbackInterface & callBackIntf;
|
||||
const casEventMask mask;
|
||||
caResId const clientId;
|
||||
unsigned char const dbrType;
|
||||
unsigned char nPend;
|
||||
bool ovf;
|
||||
bool enabled;
|
||||
void enable ();
|
||||
void disable ();
|
||||
casResType resourceType () const;
|
||||
void push ( casEventSys & evSys, const smartConstGDDPointer & pValue );
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
casMonitor ( const casMonitor & );
|
||||
casMonitor & operator = ( const casMonitor & );
|
||||
};
|
||||
|
||||
//
|
||||
// casMonitor::postEvent()
|
||||
// (check for NOOP case in line)
|
||||
//
|
||||
inline void casMonitor::postEvent ( casEventSys & evSys,
|
||||
const casEventMask & select, const smartConstGDDPointer & pValue)
|
||||
{
|
||||
casEventMask result ( select & this->mask );
|
||||
|
||||
//
|
||||
// NOOP if this event isnt selected
|
||||
// or if it is disabled
|
||||
//
|
||||
if ( result.noEventsSelected() || ! this->enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// else push it on the queue
|
||||
//
|
||||
this->push ( evSys, pValue );
|
||||
}
|
||||
|
||||
class caServer;
|
||||
class casChannelI;
|
||||
class casCtx;
|
||||
class caServer;
|
||||
class casAsyncReadIO;
|
||||
class casAsyncWriteIO;
|
||||
class casAsyncPVExistIO;
|
||||
class casAsyncPVAttachIO;
|
||||
|
||||
class casAsyncIOI : public casEvent, public tsDLNode<casAsyncIOI> {
|
||||
public:
|
||||
casAsyncIOI ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casAsyncIOI ();
|
||||
|
||||
void serverDestroyIfReadOP ();
|
||||
void serverDestroy ();
|
||||
|
||||
caServer *getCAS () const;
|
||||
|
||||
bool onTheEventQueue () const
|
||||
{
|
||||
return this->inTheEventQueue;
|
||||
}
|
||||
|
||||
protected:
|
||||
casCoreClient & client;
|
||||
|
||||
//
|
||||
// place notification of IO completion on the event queue
|
||||
//
|
||||
caStatus postIOCompletionI();
|
||||
|
||||
private:
|
||||
bool inTheEventQueue;
|
||||
bool posted;
|
||||
bool ioComplete;
|
||||
bool serverDelete;
|
||||
bool duplicate;
|
||||
|
||||
//
|
||||
// casEvent virtual call back function
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
epicsShareFunc caStatus cbFunc ( casCoreClient & );
|
||||
|
||||
epicsShareFunc void eventSysDestroyNotify ( casCoreClient & );
|
||||
|
||||
//
|
||||
// derived class specic call back
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
epicsShareFunc virtual caStatus cbFuncAsyncIO() = 0;
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
epicsShareFunc virtual bool readOP() const;
|
||||
|
||||
casAsyncIOI ( const casAsyncIOI & );
|
||||
casAsyncIOI & operator = ( const casAsyncIOI & );
|
||||
};
|
||||
|
||||
class casDGClient;
|
||||
|
||||
class casChannel;
|
||||
class casPVI;
|
||||
|
||||
//
|
||||
// casChannelI
|
||||
//
|
||||
// this derives from casEvent so that access rights
|
||||
// events can be posted
|
||||
//
|
||||
class casChannelI : public tsDLNode < casChannelI >,
|
||||
public casRes, public casEvent {
|
||||
public:
|
||||
casChannelI ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casChannelI ();
|
||||
|
||||
class casCoreClient & getClient () const
|
||||
{
|
||||
return *this->pClient;
|
||||
}
|
||||
const caResId getCID ()
|
||||
{
|
||||
return this->cid;
|
||||
}
|
||||
//
|
||||
// fetch the unsigned integer server id for this PV
|
||||
//
|
||||
const caResId getSID ();
|
||||
|
||||
void installMonitor (
|
||||
caResId clientId,
|
||||
const unsigned long count,
|
||||
const unsigned type,
|
||||
const casEventMask & );
|
||||
|
||||
bool unistallMonitor ( ca_uint32_t monId );
|
||||
|
||||
casPVI &getPVI () const
|
||||
{
|
||||
return *this->pPV;
|
||||
}
|
||||
|
||||
void installAsyncIO ( casAsyncIOI & );
|
||||
void removeAsyncIO ( casAsyncIOI & );
|
||||
|
||||
void postEvent ( const casEventMask & select, const gdd & event );
|
||||
|
||||
epicsShareFunc virtual casResType resourceType () const;
|
||||
|
||||
void destroyNoClientNotify ();
|
||||
void destroyClientNotify ();
|
||||
|
||||
void clearOutstandingReads ();
|
||||
|
||||
void postAccessRightsEvent ();
|
||||
|
||||
const gddEnumStringTable & enumStringTable () const;
|
||||
|
||||
//
|
||||
// virtual functions
|
||||
//
|
||||
epicsShareFunc virtual void setOwner ( const char * const pUserName,
|
||||
const char * const pHostName ) = 0;
|
||||
epicsShareFunc virtual bool readAccess () const = 0;
|
||||
epicsShareFunc virtual bool writeAccess () const = 0;
|
||||
epicsShareFunc virtual bool confirmationRequested () const = 0;
|
||||
epicsShareFunc virtual void show ( unsigned level ) const;
|
||||
|
||||
protected:
|
||||
tsDLList < casMonitor > monitorList;
|
||||
tsDLList < casAsyncIOI > ioInProgList;
|
||||
class casCoreClient * pClient;
|
||||
casPVI * pPV;
|
||||
caResId cid; // client id
|
||||
bool accessRightsEvPending;
|
||||
|
||||
epicsShareFunc virtual void destroy ();
|
||||
epicsShareFunc caStatus cbFunc ( casCoreClient & ); // access rights event call back
|
||||
epicsShareFunc void eventSysDestroyNotify ( casCoreClient & );
|
||||
casChannelI ( const casChannelI & );
|
||||
casChannelI & operator = ( const casChannelI & );
|
||||
};
|
||||
|
||||
//
|
||||
// class hierarchy added here solely because we need two list nodes
|
||||
//
|
||||
class casPVListChan : public casChannelI, public tsDLNode<casPVListChan>
|
||||
{
|
||||
public:
|
||||
casPVListChan ( const casCtx &ctx );
|
||||
epicsShareFunc virtual ~casPVListChan();
|
||||
private:
|
||||
casPVListChan ( const casPVListChan & );
|
||||
casPVListChan & operator = ( const casPVListChan & );
|
||||
};
|
||||
|
||||
class caServerI;
|
||||
class casCtx;
|
||||
class casChannel;
|
||||
class casPV;
|
||||
|
||||
//
|
||||
// casPVI
|
||||
//
|
||||
class casPVI :
|
||||
public tsSLNode<casPVI>, // server resource table installation
|
||||
public casRes, // server resource table installation
|
||||
public ioBlockedList // list of clients io blocked on this pv
|
||||
{
|
||||
public:
|
||||
casPVI ();
|
||||
epicsShareFunc virtual ~casPVI ();
|
||||
caServerI *getPCAS () const;
|
||||
caStatus attachToServer ( caServerI & cas );
|
||||
aitIndex nativeCount ();
|
||||
caStatus registerEvent ();
|
||||
void unregisterEvent ();
|
||||
void unregisterIO ();
|
||||
void installChannel ( casPVListChan & chan );
|
||||
void removeChannel ( casPVListChan & chan );
|
||||
void deleteSignal ();
|
||||
void postEvent ( const casEventMask & select, const gdd & event );
|
||||
caServer * getExtServer () const;
|
||||
caStatus bestDBRType ( unsigned & dbrType );
|
||||
epicsShareFunc virtual casResType resourceType () const;
|
||||
const gddEnumStringTable & enumStringTable () const;
|
||||
caStatus updateEnumStringTable ( casCtx & );
|
||||
void updateEnumStringTableAsyncCompletion ( const gdd & resp );
|
||||
|
||||
//
|
||||
// virtual functions in the public interface class
|
||||
//
|
||||
epicsShareFunc virtual void show ( unsigned level ) const;
|
||||
epicsShareFunc virtual caStatus interestRegister () = 0;
|
||||
epicsShareFunc virtual void interestDelete () = 0;
|
||||
epicsShareFunc virtual caStatus beginTransaction () = 0;
|
||||
epicsShareFunc virtual void endTransaction () = 0;
|
||||
epicsShareFunc virtual caStatus read ( const casCtx & ctx, gdd & prototype ) = 0;
|
||||
epicsShareFunc virtual caStatus write ( const casCtx & ctx, const gdd & value ) = 0;
|
||||
epicsShareFunc virtual casChannel * createChannel ( const casCtx & ctx,
|
||||
const char * const pUserName, const char * const pHostName ) = 0;
|
||||
epicsShareFunc virtual aitEnum bestExternalType () const = 0;
|
||||
epicsShareFunc virtual unsigned maxDimension () const = 0;
|
||||
epicsShareFunc virtual aitIndex maxBound ( unsigned dimension ) const = 0;
|
||||
epicsShareFunc virtual const char * getName () const = 0;
|
||||
epicsShareFunc casPV *apiPointer (); //retuns NULL if casPVI isnt a base of casPV
|
||||
|
||||
private:
|
||||
tsDLList < casPVListChan > chanList;
|
||||
gddEnumStringTable enumStrTbl;
|
||||
caServerI * pCAS;
|
||||
unsigned nMonAttached;
|
||||
unsigned nIOAttached;
|
||||
bool destroyInProgress;
|
||||
|
||||
epicsShareFunc virtual void destroy (); // casPVI destructor noop
|
||||
casPVI ( const casPVI & );
|
||||
casPVI & operator = ( const casPVI & );
|
||||
};
|
||||
|
||||
/* a modified ca header with capacity for large arrays */
|
||||
struct caHdrLargeArray {
|
||||
ca_uint32_t m_postsize; /* size of message extension */
|
||||
ca_uint32_t m_count; /* operation data count */
|
||||
ca_uint32_t m_cid; /* channel identifier */
|
||||
ca_uint32_t m_available; /* protocol stub dependent */
|
||||
ca_uint16_t m_dataType; /* operation data type */
|
||||
ca_uint16_t m_cmmd; /* operation to be performed */
|
||||
};
|
||||
|
||||
|
||||
@@ -17,72 +17,36 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
#include "casMonEventIL.h" // casMonEvent in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casMonEvent.h"
|
||||
#include "casMonitor.h"
|
||||
#include "casCoreClient.h"
|
||||
|
||||
//
|
||||
// casMonEvent::cbFunc()
|
||||
//
|
||||
caStatus casMonEvent::cbFunc ( casCoreClient & client )
|
||||
caStatus casMonEvent::cbFunc (
|
||||
casCoreClient & client, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
//
|
||||
// ignore this event if it is stale and there is
|
||||
// no call back object associated with it
|
||||
//
|
||||
casMonitor * pMon = client.lookupMonitor ( this->id );
|
||||
if ( ! pMon ) {
|
||||
// we know this isnt an overflow event because those are
|
||||
// removed from the queue when the casMonitor object is
|
||||
// destroyed
|
||||
client.casMonEventDestroy ( *this );
|
||||
status = S_casApp_success;
|
||||
}
|
||||
else {
|
||||
// this object may have been destroyed
|
||||
// here by the executeEvent() call below
|
||||
status = pMon->executeEvent ( *this );
|
||||
}
|
||||
|
||||
return status;
|
||||
return this->monitor.executeEvent (
|
||||
client, * this, this->pValue, guard );
|
||||
}
|
||||
|
||||
void casMonEvent::eventSysDestroyNotify ( casCoreClient & client )
|
||||
void casMonEvent::assign ( const gdd & valueIn )
|
||||
{
|
||||
client.casMonEventDestroy ( *this );
|
||||
this->pValue = & valueIn;
|
||||
}
|
||||
|
||||
//
|
||||
// casMonEvent::assign ()
|
||||
//
|
||||
void casMonEvent::assign (casMonitor &monitor, const smartConstGDDPointer &pValueIn)
|
||||
void casMonEvent::swapValues ( casMonEvent & in )
|
||||
{
|
||||
this->pValue = pValueIn;
|
||||
this->id = monitor.casRes::getId();
|
||||
assert ( & in.monitor == & this->monitor );
|
||||
this->pValue.swap ( in.pValue );
|
||||
}
|
||||
|
||||
//
|
||||
// ~casMonEvent ()
|
||||
// (this is not in line because it is virtual in the base)
|
||||
//
|
||||
casMonEvent::~casMonEvent ()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void * casMonEvent::operator new ( size_t size,
|
||||
tsFreeList < class casMonEvent, 1024 > & freeList )
|
||||
{
|
||||
return freeList.allocate ( size );
|
||||
}
|
||||
|
||||
#ifdef CXX_PLACEMENT_DELETE
|
||||
void casMonEvent::operator delete ( void *pCadaver,
|
||||
tsFreeList < class casMonEvent, 1024 > & freeList ) epicsThrows(())
|
||||
void casMonEvent::operator delete ( void * pCadaver,
|
||||
tsFreeList < class casMonEvent, 1024, epicsMutexNOOP > & freeList )
|
||||
{
|
||||
freeList.release ( pCadaver, sizeof ( casMonEvent ) );
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef casMonEventIL_h
|
||||
#define casMonEventIL_h
|
||||
|
||||
//
|
||||
// casMonEvent::casMonEvent()
|
||||
//
|
||||
inline casMonEvent::casMonEvent () :
|
||||
id(0u) {}
|
||||
|
||||
//
|
||||
// casMonEvent::casMonEvent()
|
||||
//
|
||||
inline casMonEvent::casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue) :
|
||||
pValue ( pNewValue ),
|
||||
id ( monitor.casRes::getId () ) {}
|
||||
|
||||
//
|
||||
// casMonEvent::casMonEvent()
|
||||
//
|
||||
inline casMonEvent::casMonEvent (const casMonEvent &initValue) :
|
||||
pValue ( initValue.pValue ),
|
||||
id ( initValue.id ) {}
|
||||
|
||||
//
|
||||
// casMonEvent::operator = ()
|
||||
//
|
||||
inline void casMonEvent::operator = (const class casMonEvent &monEventIn)
|
||||
{
|
||||
this->pValue = monEventIn.pValue;
|
||||
this->id = monEventIn.id;
|
||||
}
|
||||
|
||||
//
|
||||
// casMonEvent::clear()
|
||||
//
|
||||
inline void casMonEvent::clear()
|
||||
{
|
||||
this->pValue = NULL;
|
||||
this->id = 0u;
|
||||
}
|
||||
|
||||
//
|
||||
// casMonEvent::getValue()
|
||||
//
|
||||
inline smartConstGDDPointer casMonEvent::getValue() const
|
||||
{
|
||||
return this->pValue;
|
||||
}
|
||||
|
||||
#endif // casMonEventIL_h
|
||||
|
||||
@@ -15,229 +15,151 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casMonitor.h"
|
||||
#include "casChannelI.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI inline func
|
||||
#include "casEventSysIL.h" // casEventSys inline func
|
||||
#include "casMonEventIL.h" // casMonEvent inline func
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
casEvent::~casEvent () {}
|
||||
|
||||
|
||||
//
|
||||
// casMonitor::casMonitor()
|
||||
//
|
||||
casMonitor::casMonitor (
|
||||
caResId clientIdIn,
|
||||
casChannelI & chan,
|
||||
unsigned long nElemIn,
|
||||
ca_uint32_t nElemIn,
|
||||
unsigned dbrTypeIn,
|
||||
const casEventMask & maskIn,
|
||||
casMonitorCallbackInterface & cb ) :
|
||||
overFlowEvent ( *this ),
|
||||
nElem ( nElemIn ),
|
||||
ciu ( chan ),
|
||||
pChannel ( & chan ),
|
||||
callBackIntf ( cb ),
|
||||
mask ( maskIn ),
|
||||
clientId ( clientIdIn ),
|
||||
dbrType ( static_cast <unsigned char> ( dbrTypeIn ) ),
|
||||
nPend ( 0u ),
|
||||
ovf ( false ),
|
||||
enabled ( false )
|
||||
ovf ( false )
|
||||
{
|
||||
assert ( &this->ciu );
|
||||
assert ( dbrTypeIn <= 0xff );
|
||||
this->enable();
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::~casMonitor()
|
||||
//
|
||||
casMonitor::~casMonitor()
|
||||
{
|
||||
this->disable();
|
||||
if ( this->ovf ) {
|
||||
casCoreClient &client = this->ciu.getClient();
|
||||
client.removeFromEventQueue ( this->overFlowEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::enable()
|
||||
//
|
||||
void casMonitor::enable()
|
||||
caStatus casMonitor::response ( casCoreClient & client,
|
||||
const smartConstGDDPointer & value )
|
||||
{
|
||||
if ( ! this->enabled && this->ciu.readAccess() ) {
|
||||
this->enabled = true;
|
||||
caStatus status = this->ciu.getPVI().registerEvent();
|
||||
if ( status ) {
|
||||
errMessage ( status,
|
||||
"Server tool failed to register event\n" );
|
||||
}
|
||||
}
|
||||
if ( this->pChannel ) {
|
||||
// reconstruct request header
|
||||
caHdrLargeArray msg;
|
||||
msg.m_cmmd = CA_PROTO_EVENT_ADD;
|
||||
msg.m_postsize = 0u;
|
||||
msg.m_dataType = this->dbrType;
|
||||
msg.m_count = this->nElem;
|
||||
msg.m_cid = this->pChannel->getSID();
|
||||
msg.m_available = this->clientId;
|
||||
return client.monitorResponse ( *this->pChannel,
|
||||
msg, value, S_cas_success );
|
||||
}
|
||||
else {
|
||||
return S_cas_success;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::disable()
|
||||
//
|
||||
void casMonitor::disable()
|
||||
void casMonitor::installNewEventLog (
|
||||
tsDLList < casEvent > & eventLogQue,
|
||||
casMonEvent * pLog, const gdd & event )
|
||||
{
|
||||
if ( this->enabled ) {
|
||||
this->enabled = false;
|
||||
this->ciu.getPVI().unregisterEvent();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::push()
|
||||
//
|
||||
void casMonitor::push ( casEventSys & evSys,
|
||||
const smartConstGDDPointer & pNewValue )
|
||||
{
|
||||
casCoreClient & client = this->ciu.getClient ();
|
||||
client.getCAS().incrEventsPostedCounter ();
|
||||
|
||||
//
|
||||
// get a new block if we havent exceeded quotas
|
||||
//
|
||||
bool full = ( this->nPend >= individualEventEntries ) || evSys.full ();
|
||||
casMonEvent * pLog;
|
||||
if ( ! full ) {
|
||||
try {
|
||||
// I should get rid of this try block by implementing a no
|
||||
// throw version of the free list alloc
|
||||
pLog = & client.casMonEventFactory ( *this, pNewValue );
|
||||
assert ( this->nPend != UCHAR_MAX );
|
||||
this->nPend++; // X aCC 818
|
||||
}
|
||||
catch ( ... ) {
|
||||
pLog = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pLog = 0;
|
||||
}
|
||||
|
||||
if ( this->ovf ) {
|
||||
if ( pLog ) {
|
||||
// swap values
|
||||
smartConstGDDPointer pOldValue = this->overFlowEvent.getValue ();
|
||||
if ( ! pOldValue ) {
|
||||
assert ( 0 ); // due to limitations in class smartConstGDDPointer
|
||||
}
|
||||
// copy old OVF value into the new entry which must remain
|
||||
// ordered in the queue where the OVF entry was before
|
||||
pLog->assign ( *this, pOldValue );
|
||||
// copy new value into OVF event entry which must be last
|
||||
this->overFlowEvent.assign ( *this, *pNewValue );
|
||||
// this inserts it out of order, but this is fixed below when the
|
||||
// overflow event is removed from the queue
|
||||
evSys.insertEventQueue ( *pLog, this->overFlowEvent );
|
||||
pLog->assign ( event );
|
||||
this->overFlowEvent.swapValues ( *pLog );
|
||||
eventLogQue.insertAfter ( *pLog, this->overFlowEvent );
|
||||
assert ( this->nPend != UCHAR_MAX );
|
||||
this->nPend++; // X aCC 818
|
||||
}
|
||||
else {
|
||||
// replace the old OVF value with the current one
|
||||
this->overFlowEvent.assign ( *this, pNewValue );
|
||||
this->overFlowEvent.assign ( event );
|
||||
}
|
||||
// remove OVF entry (with its new value) from the queue so
|
||||
// that it ends up properly ordered at the back of the
|
||||
// queue
|
||||
evSys.removeFromEventQueue ( this->overFlowEvent );
|
||||
eventLogQue.remove ( this->overFlowEvent );
|
||||
pLog = & this->overFlowEvent;
|
||||
}
|
||||
else if ( ! pLog ) {
|
||||
//
|
||||
// no log block
|
||||
// => use the over flow block in the event structure
|
||||
//
|
||||
this->ovf = true;
|
||||
this->overFlowEvent.assign ( * this, pNewValue );
|
||||
else {
|
||||
if ( pLog == 0 ) {
|
||||
// use the over flow block in the event structure
|
||||
this->ovf = true;
|
||||
pLog = & this->overFlowEvent;
|
||||
}
|
||||
pLog->assign ( event );
|
||||
assert ( this->nPend != UCHAR_MAX );
|
||||
this->nPend++; // X aCC 818
|
||||
pLog = &this->overFlowEvent;
|
||||
}
|
||||
|
||||
evSys.addToEventQueue ( * pLog );
|
||||
}
|
||||
eventLogQue.add ( *pLog );
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::executeEvent()
|
||||
//
|
||||
caStatus casMonitor::executeEvent ( casMonEvent & ev )
|
||||
caStatus casMonitor::executeEvent ( casCoreClient & client,
|
||||
casMonEvent & ev, smartConstGDDPointer & pValue,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
smartConstGDDPointer pVal = ev.getValue ();
|
||||
if ( ! pVal ) {
|
||||
assert ( 0 );
|
||||
assert ( pValue.valid() );
|
||||
|
||||
if ( this->pChannel ) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
caStatus status = this->callBackIntf.casMonitorCallBack (
|
||||
*this, pValue );
|
||||
if ( status != S_cas_success ) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
caStatus status;
|
||||
{
|
||||
status =
|
||||
this->callBackIntf.
|
||||
casMonitorCallBack ( *this, *pVal );
|
||||
}
|
||||
|
||||
//
|
||||
// if the event isnt accepted we will try
|
||||
// again later (and the event returns to the queue)
|
||||
//
|
||||
if ( status ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// decrement the count of the number of events pending
|
||||
//
|
||||
|
||||
client.getCAS().incrEventsProcessedCounter ();
|
||||
assert ( this->nPend != 0u );
|
||||
this->nPend--; // X aCC 818
|
||||
|
||||
//
|
||||
|
||||
// delete event object if it isnt a cache entry
|
||||
// saved in the call back object
|
||||
//
|
||||
if ( &ev == &this->overFlowEvent ) {
|
||||
if ( & ev == & this->overFlowEvent ) {
|
||||
assert ( this->ovf );
|
||||
this->ovf = false;
|
||||
ev.clear();
|
||||
this->overFlowEvent.clear ();
|
||||
}
|
||||
else {
|
||||
this->ciu.getClient().casMonEventDestroy ( ev );
|
||||
client.casMonEventDestroy ( ev, guard );
|
||||
}
|
||||
|
||||
this->ciu.getClient().getCAS().incrEventsProcessedCounter ();
|
||||
|
||||
return S_cas_success;
|
||||
if ( ! this->pChannel && this->nPend == 0 ) {
|
||||
// we are careful here not to invert
|
||||
// the lock hierarchy
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
client.destroyMonitor ( *this );
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::show(unsigned level)
|
||||
//
|
||||
void casMonitor::show ( unsigned level ) const
|
||||
{
|
||||
if ( level > 1u ) {
|
||||
printf (
|
||||
"\tmonitor type=%u count=%lu client id=%u enabled=%u OVF=%u nPend=%u\n",
|
||||
dbrType, nElem, clientId, enabled, ovf, nPend );
|
||||
"\tmonitor type=%u count=%lu client id=%u OVF=%u nPend=%u\n",
|
||||
dbrType, nElem, clientId, ovf, nPend );
|
||||
this->mask.show ( level );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casMonitor::resourceType()
|
||||
//
|
||||
casResType casMonitor::resourceType() const
|
||||
{
|
||||
return casMonitorT;
|
||||
}
|
||||
|
||||
void * casMonitor::operator new (
|
||||
size_t size,
|
||||
tsFreeList < casMonitor, 1024 > & freeList )
|
||||
epicsThrows ( ( std::bad_alloc ) )
|
||||
{
|
||||
return freeList.allocate ( size );
|
||||
}
|
||||
|
||||
#ifdef CXX_PLACEMENT_DELETE
|
||||
void casMonitor::operator delete ( void * pCadaver,
|
||||
tsFreeList < casMonitor, 1024 > & freeList ) epicsThrows(())
|
||||
tsFreeList < casMonitor, 1024 > & freeList )
|
||||
{
|
||||
freeList.release ( pCadaver );
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
|
||||
//
|
||||
|
||||
@@ -15,17 +15,10 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// 1) Always verify that pPVI isnt nill prior to using it
|
||||
//
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casPVI.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "casPVIIL.h" // casPVI inline func
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
|
||||
casPV::casPV ()
|
||||
casPV::casPV () : pPVI ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -33,7 +26,7 @@ casPV::casPV ()
|
||||
// This constructor is preserved for backwards compatibility only.
|
||||
// Please do _not_ use this constructor.
|
||||
//
|
||||
casPV::casPV (caServer &)
|
||||
casPV::casPV ( caServer & ) : pPVI ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -136,17 +129,18 @@ aitIndex casPV::maxBound (unsigned /* dimension */) const
|
||||
//
|
||||
// casPV::show (unsigned level)
|
||||
//
|
||||
void casPV::show (unsigned level) const
|
||||
void casPV::show ( unsigned /* level */ ) const
|
||||
{
|
||||
casPVI::show (level);
|
||||
}
|
||||
|
||||
//
|
||||
// Server tool calls this function to post a PV event.
|
||||
//
|
||||
void casPV::postEvent (const casEventMask &select, const gdd &event)
|
||||
void casPV::postEvent ( const casEventMask &select, const gdd &event )
|
||||
{
|
||||
this->casPVI::postEvent (select, event);
|
||||
if ( this->pPVI ) {
|
||||
this->pPVI->postEvent ( select, event );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -156,16 +150,14 @@ void casPV::postEvent (const casEventMask &select, const gdd &event)
|
||||
// into a server.
|
||||
// ***************
|
||||
//
|
||||
caServer *casPV::getCAS () const
|
||||
caServer * casPV::getCAS () const
|
||||
{
|
||||
return this->casPVI::getExtServer ();
|
||||
if ( this->pPVI ) {
|
||||
return this->pPVI->getExtServer ();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casPV::apiPointer()
|
||||
//
|
||||
casPV *casPV::apiPointer ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,118 +15,92 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "epicsGuard.h"
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
#include "gddApps.h"
|
||||
#include "dbMapper.h" // EPICS application type table
|
||||
|
||||
#include "server.h"
|
||||
#include "casPVIIL.h" // caServerI inline func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caServerDefs.h"
|
||||
#include "caServerI.h"
|
||||
#include "casPVI.h"
|
||||
#include "chanIntfForPV.h"
|
||||
#include "casAsyncIOI.h"
|
||||
#include "casMonitor.h"
|
||||
|
||||
casRes::casRes () {}
|
||||
casPVI::casPVI ( casPV & intf ) :
|
||||
pCAS ( NULL ), pv ( intf ),
|
||||
nMonAttached ( 0u ), nIOAttached ( 0u ) {}
|
||||
|
||||
//
|
||||
// casPVI::casPVI()
|
||||
//
|
||||
casPVI::casPVI () :
|
||||
pCAS (NULL), // initially there is no server attachment
|
||||
nMonAttached (0u),
|
||||
nIOAttached (0u),
|
||||
destroyInProgress (false)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::~casPVI()
|
||||
//
|
||||
casPVI::~casPVI ()
|
||||
{
|
||||
this->destroyInProgress = true;
|
||||
|
||||
//
|
||||
// only relevant if we are attached to a server
|
||||
// all channels should have been destroyed
|
||||
// (otherwise the server tool is yanking the
|
||||
// PV out from under the server)
|
||||
//
|
||||
if ( this->pCAS != NULL ) {
|
||||
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
|
||||
this->pCAS->removeItem ( *this );
|
||||
|
||||
//
|
||||
// delete any attached channels
|
||||
//
|
||||
tsDLIter < casPVListChan > iter = this->chanList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
tsDLIter < casPVListChan > tmp = iter;
|
||||
++tmp;
|
||||
iter->destroyClientNotify ();
|
||||
iter = tmp;
|
||||
}
|
||||
}
|
||||
casVerify ( this->chanList.count() == 0u );
|
||||
|
||||
//
|
||||
// all outstanding IO should have been deleted
|
||||
// when we destroyed the channels
|
||||
//
|
||||
casVerify ( this->nIOAttached == 0u );
|
||||
if (this->nIOAttached) {
|
||||
errlogPrintf ( "The number of IO objected supposedly attached is %u\n", this->nIOAttached );
|
||||
}
|
||||
|
||||
//
|
||||
// all monitors should have been deleted
|
||||
// when we destroyed the channels
|
||||
//
|
||||
casVerify ( this->nMonAttached == 0u );
|
||||
|
||||
this->pv.pPVI = 0;
|
||||
this->pv.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::deleteSignal()
|
||||
// check for none attached and delete self if so
|
||||
//
|
||||
// this call must be protected by the server's lock
|
||||
// ( which also protects channel creation)
|
||||
//
|
||||
void casPVI::deleteSignal ()
|
||||
{
|
||||
//
|
||||
// if we are not attached to a server then the
|
||||
// following steps are not relevant
|
||||
//
|
||||
if ( this->pCAS ) {
|
||||
//
|
||||
// We dont take the PV lock here because
|
||||
// the PV may be destroyed and we must
|
||||
// keep the lock unlock pairs consistent
|
||||
// (because the PV's lock is really a ref
|
||||
// to the server's lock)
|
||||
//
|
||||
// This is safe to do because we take the PV
|
||||
// lock when we add a new channel (and the
|
||||
// PV lock is realy the server's lock)
|
||||
//
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
bool destroyNeeded = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
if ( this->chanList.count() == 0u ) {
|
||||
this->pCAS->removeItem ( *this );
|
||||
this->pCAS = NULL;
|
||||
// refresh the table whenever the server reattaches to the PV
|
||||
this->enumStrTbl.clear ();
|
||||
this->destroy ();
|
||||
//
|
||||
// !! dont access self after destroy !!
|
||||
//
|
||||
}
|
||||
}
|
||||
//
|
||||
// if we are not attached to a server then the
|
||||
// following steps are not relevant
|
||||
//
|
||||
if ( this->pCAS ) {
|
||||
if ( this->chanList.count() == 0u ) {
|
||||
this->pCAS = NULL;
|
||||
// refresh the table whenever the server reattaches to the PV
|
||||
this->enumStrTbl.clear ();
|
||||
destroyNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( destroyNeeded ) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
// !! dont access self after potential delete above !!
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::destroy()
|
||||
//
|
||||
// This version of destroy() is provided only because it can
|
||||
// be safely called in the casPVI destructor as a side effect
|
||||
// of deleting the last channel.
|
||||
//
|
||||
void casPVI::destroy ()
|
||||
casPVI * casPVI::attachPV ( casPV & pv )
|
||||
{
|
||||
if ( ! pv.pPVI ) {
|
||||
pv.pPVI = new ( std::nothrow ) casPVI ( pv );
|
||||
}
|
||||
return pv.pPVI;
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::attachToServer ()
|
||||
//
|
||||
caStatus casPVI::attachToServer ( caServerI & cas )
|
||||
{
|
||||
if ( this->pCAS ) {
|
||||
@@ -139,11 +113,7 @@ caStatus casPVI::attachToServer ( caServerI & cas )
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// install the PV into the server
|
||||
//
|
||||
cas.installItem ( *this );
|
||||
this->pCAS = &cas;
|
||||
this->pCAS = & cas;
|
||||
}
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -216,6 +186,8 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctx )
|
||||
|
||||
void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
//
|
||||
// keep trying to fill in the table if client disconnects
|
||||
// prevented previous asynchronous IO from finishing, but if
|
||||
@@ -297,85 +269,193 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::registerEvent()
|
||||
//
|
||||
caStatus casPVI::registerEvent ()
|
||||
void casPVI::postEvent ( const casEventMask & select, const gdd & event )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
this->nMonAttached++;
|
||||
if ( this->nMonAttached == 1u ) {
|
||||
status = this->interestRegister ();
|
||||
}
|
||||
else {
|
||||
status = S_cas_success;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::unregisterEvent()
|
||||
//
|
||||
void casPVI::unregisterEvent()
|
||||
{
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
this->nMonAttached--;
|
||||
//
|
||||
// Dont call casPV::interestDelete() when we are in
|
||||
// casPVI::~casPVI() (and casPV no longr exists)
|
||||
//
|
||||
if ( this->nMonAttached == 0u && !this->destroyInProgress ) {
|
||||
this->interestDelete();
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( this->nMonAttached ) {
|
||||
// we are paying some significant locking overhead for
|
||||
// these diagnostic counters
|
||||
this->pCAS->updateEventsPostedCounter ( this->nMonAttached );
|
||||
tsDLIter < chanIntfForPV > iter = this->chanList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->postEvent ( select, event );
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::getExtServer()
|
||||
// (not inline because details of caServerI must not
|
||||
// leak into server tool)
|
||||
//
|
||||
caServer *casPVI::getExtServer() const // X aCC 361
|
||||
caStatus casPVI::installMonitor (
|
||||
casMonitor & mon, tsDLList < casMonitor > & monitorList )
|
||||
{
|
||||
if (this->pCAS) {
|
||||
return this->pCAS->getAdapter();
|
||||
bool newInterest = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
assert ( this->nMonAttached < UINT_MAX );
|
||||
this->nMonAttached++;
|
||||
if ( this->nMonAttached == 1u ) {
|
||||
newInterest = true;
|
||||
}
|
||||
// use pv lock to protect channel's monitor list
|
||||
monitorList.add ( mon );
|
||||
}
|
||||
if ( newInterest ) {
|
||||
return this->pv.interestRegister ();
|
||||
}
|
||||
else {
|
||||
return S_cas_success;
|
||||
}
|
||||
}
|
||||
|
||||
casMonitor * casPVI::removeMonitor (
|
||||
tsDLList < casMonitor > & list, ca_uint32_t clientIdIn )
|
||||
{
|
||||
casMonitor * pMon = 0;
|
||||
bool noInterest = false;
|
||||
{
|
||||
//
|
||||
// (it is reasonable to do a linear search here because
|
||||
// sane clients will require only one or two monitors
|
||||
// per channel)
|
||||
//
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
tsDLIter < casMonitor > iter = list.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
if ( iter->matchingClientId ( clientIdIn ) ) {
|
||||
list.remove ( *iter.pointer () );
|
||||
assert ( this->nMonAttached > 0 );
|
||||
this->nMonAttached--;
|
||||
noInterest =
|
||||
( this->nMonAttached == 0u );
|
||||
pMon = iter.pointer ();
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
if ( noInterest ) {
|
||||
this->pv.interestDelete ();
|
||||
}
|
||||
return pMon;
|
||||
}
|
||||
|
||||
caServer *casPVI::getExtServer () const // X aCC 361
|
||||
{
|
||||
if ( this->pCAS ) {
|
||||
return this->pCAS->getAdapter ();
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::show()
|
||||
//
|
||||
void casPVI::show (unsigned level) const
|
||||
void casPVI::show ( unsigned level ) const
|
||||
{
|
||||
if (level>1u) {
|
||||
printf ("CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n",
|
||||
this->chanList.count(), this->nMonAttached, this->nIOAttached);
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
printf ( "CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n",
|
||||
this->chanList.count(), this->nMonAttached, this->nIOAttached );
|
||||
if ( level >= 1u ) {
|
||||
printf ( "\tBest external type = %d\n", this->bestExternalType() );
|
||||
}
|
||||
if (level>2u) {
|
||||
printf ("\tBest external type = %d\n", this->bestExternalType());
|
||||
if ( level >= 2u ) {
|
||||
this->pv.show ( level - 2u );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::resourceType()
|
||||
//
|
||||
casResType casPVI::resourceType() const
|
||||
casPV * casPVI::apiPointer ()
|
||||
{
|
||||
return casPVT;
|
||||
return & this->pv;
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::apiPointer()
|
||||
// retuns NULL if casPVI isnt a base of casPV
|
||||
//
|
||||
casPV *casPVI::apiPointer ()
|
||||
void casPVI::installChannel ( chanIntfForPV & chan )
|
||||
{
|
||||
return NULL;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->chanList.add ( chan );
|
||||
}
|
||||
|
||||
void casPVI::removeChannel (
|
||||
chanIntfForPV & chan, tsDLList < casMonitor > & src,
|
||||
tsDLList < casMonitor > & dest )
|
||||
{
|
||||
bool noInterest = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
src.removeAll ( dest );
|
||||
if ( dest.count() ) {
|
||||
assert ( this->nMonAttached >= dest.count() );
|
||||
this->nMonAttached -= dest.count ();
|
||||
noInterest = ( this->nMonAttached == 0u );
|
||||
}
|
||||
this->chanList.remove ( chan );
|
||||
}
|
||||
if ( noInterest ) {
|
||||
this->pv.interestDelete ();
|
||||
}
|
||||
}
|
||||
|
||||
void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
// cancel any pending asynchronous IO
|
||||
tsDLIter < casAsyncIOI > iterIO =
|
||||
ioList.firstIter ();
|
||||
while ( iterIO.valid () ) {
|
||||
tsDLIter < casAsyncIOI > tmp = iterIO;
|
||||
++tmp;
|
||||
if ( iterIO->oneShotReadOP () ) {
|
||||
ioList.remove ( *iterIO );
|
||||
assert ( this->nIOAttached != 0 );
|
||||
this->nIOAttached--;
|
||||
}
|
||||
delete iterIO.pointer ();
|
||||
iterIO = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
while ( casAsyncIOI * pIO = ioList.get() ) {
|
||||
pIO->removeFromEventQueue ();
|
||||
delete pIO;
|
||||
assert ( this->nIOAttached != 0 );
|
||||
this->nIOAttached--;
|
||||
}
|
||||
}
|
||||
|
||||
void casPVI::installIO (
|
||||
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
ioList.add ( io );
|
||||
assert ( this->nIOAttached != UINT_MAX );
|
||||
this->nIOAttached++;
|
||||
}
|
||||
|
||||
void casPVI::uninstallIO (
|
||||
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
ioList.remove ( io );
|
||||
assert ( this->nIOAttached != 0 );
|
||||
this->nIOAttached--;
|
||||
}
|
||||
this->ioBlockedList::signal();
|
||||
}
|
||||
|
||||
caStatus casPVI::bestDBRType ( unsigned & dbrType ) // X aCC 361
|
||||
{
|
||||
aitEnum bestAIT = this->bestExternalType ();
|
||||
if ( bestAIT == aitEnumInvalid || bestAIT < 0 ) {
|
||||
return S_cas_badType;
|
||||
}
|
||||
unsigned aitIndex = static_cast < unsigned > ( bestAIT );
|
||||
if ( aitIndex >= sizeof ( gddAitToDbr ) / sizeof ( gddAitToDbr[0] ) ) {
|
||||
return S_cas_badType;
|
||||
}
|
||||
dbrType = gddAitToDbr[bestAIT];
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef casPVIIL_h
|
||||
#define casPVIIL_h
|
||||
|
||||
#include "dbMapper.h"
|
||||
#include "caServerIIL.h"
|
||||
|
||||
//
|
||||
// casPVI::getPCAS()
|
||||
//
|
||||
inline caServerI *casPVI::getPCAS() const
|
||||
{
|
||||
return this->pCAS;
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::installChannel()
|
||||
//
|
||||
inline void casPVI::installChannel ( casPVListChan & chan )
|
||||
{
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
this->chanList.add(chan);
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::removeChannel()
|
||||
//
|
||||
inline void casPVI::removeChannel ( casPVListChan & chan )
|
||||
{
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
this->chanList.remove(chan);
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::unregisterIO()
|
||||
//
|
||||
inline void casPVI::unregisterIO()
|
||||
{
|
||||
this->ioBlockedList::signal();
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::bestDBRType()
|
||||
//
|
||||
inline caStatus casPVI::bestDBRType ( unsigned & dbrType ) // X aCC 361
|
||||
{
|
||||
aitEnum bestAIT = this->bestExternalType ();
|
||||
if ( bestAIT == aitEnumInvalid || bestAIT < 0 ) {
|
||||
return S_cas_badType;
|
||||
}
|
||||
unsigned aitIndex = static_cast < unsigned > ( bestAIT );
|
||||
if ( aitIndex >= NELEMENTS ( gddAitToDbr ) ) {
|
||||
return S_cas_badType;
|
||||
}
|
||||
dbrType = gddAitToDbr[bestAIT];
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
#include "casChannelIIL.h" // inline func for casChannelI
|
||||
|
||||
//
|
||||
// functions that use casChannelIIL.h below here
|
||||
//
|
||||
|
||||
//
|
||||
// casPVI::postEvent()
|
||||
//
|
||||
inline void casPVI::postEvent (const casEventMask &select, const gdd &event)
|
||||
{
|
||||
if ( this->nMonAttached == 0u ) {
|
||||
return;
|
||||
}
|
||||
|
||||
epicsGuard < caServerI > guard ( * this->pCAS );
|
||||
tsDLIter < casPVListChan > iter = this->chanList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->postEvent ( select, event );
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CA only does 1D arrays for now
|
||||
//
|
||||
inline aitIndex casPVI::nativeCount ()
|
||||
{
|
||||
if (this->maxDimension()==0u) {
|
||||
return 1u; // scalar
|
||||
}
|
||||
return this->maxBound(0u);
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::enumStringTable ()
|
||||
//
|
||||
inline const gddEnumStringTable & casPVI::enumStringTable () const
|
||||
{
|
||||
return this->enumStrTbl;
|
||||
}
|
||||
|
||||
#endif // casPVIIL_h
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "casPVIIL.h"
|
||||
|
||||
//
|
||||
// casPVListChan::casPVListChan()
|
||||
//
|
||||
casPVListChan::casPVListChan (const casCtx &ctx) :
|
||||
casChannelI(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casPVListChan::~casPVListChan()
|
||||
//
|
||||
casPVListChan::~casPVListChan()
|
||||
{
|
||||
this->pPV->removeChannel(*this);
|
||||
//
|
||||
// delete signal to PV occurs in
|
||||
// casChannelI::~casChannelI
|
||||
//
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
|
||||
#ifndef casPVListChanIL_h
|
||||
#define casPVListChanIL_h
|
||||
|
||||
#include "casPVIIL.h"
|
||||
|
||||
//
|
||||
// empty for now since casPVListChan::casPVListChan()
|
||||
// causes undefined sym when it is inline under g++ 2.7.x
|
||||
// (without -O)
|
||||
//
|
||||
|
||||
#endif // casPVListChanIL_h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
138
src/cas/generic/casStrmClient.h
Normal file
138
src/cas/generic/casStrmClient.h
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef casStrmClienth
|
||||
#define casStrmClienth
|
||||
|
||||
#include "casClient.h"
|
||||
|
||||
enum xBlockingStatus { xIsBlocking, xIsntBlocking };
|
||||
|
||||
//
|
||||
// casStrmClient
|
||||
//
|
||||
class casStrmClient :
|
||||
public casClient,
|
||||
public tsDLNode < casStrmClient > {
|
||||
public:
|
||||
casStrmClient ( caServerI &, clientBufMemoryManager & );
|
||||
virtual ~casStrmClient();
|
||||
void show ( unsigned level ) const;
|
||||
void flush ();
|
||||
|
||||
//
|
||||
// one function for each CA request type that has
|
||||
// asynchronous completion
|
||||
//
|
||||
virtual caStatus createChanResponse (
|
||||
const caHdrLargeArray &, const pvAttachReturn & );
|
||||
caStatus readResponse ( casChannelI *pChan, const caHdrLargeArray &msg,
|
||||
const smartConstGDDPointer &pDesc, const caStatus status);
|
||||
caStatus readNotifyResponse ( casChannelI *pChan, const caHdrLargeArray &msg,
|
||||
const smartConstGDDPointer &pDesc, const caStatus status);
|
||||
caStatus writeResponse ( casChannelI &,
|
||||
const caHdrLargeArray & msg, const caStatus status );
|
||||
caStatus writeNotifyResponse ( casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus status );
|
||||
caStatus monitorResponse ( casChannelI & chan, const caHdrLargeArray & msg,
|
||||
const smartConstGDDPointer & pDesc, const caStatus status );
|
||||
caStatus enumPostponedCreateChanResponse ( casChannelI & chan,
|
||||
const caHdrLargeArray & hdr, unsigned dbrType );
|
||||
caStatus channelCreateFailedResp ( const caHdrLargeArray &,
|
||||
const caStatus createStatus );
|
||||
|
||||
caStatus disconnectChan ( caResId id );
|
||||
unsigned getDebugLevel () const;
|
||||
virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
|
||||
private:
|
||||
chronIntIdResTable < casChannelI > chanTable;
|
||||
tsDLList < casChannelI > chanList;
|
||||
char * pUserName;
|
||||
char * pHostName;
|
||||
|
||||
//
|
||||
// createChannel()
|
||||
//
|
||||
caStatus createChannel ( const char *pName );
|
||||
|
||||
//
|
||||
// verify read/write requests
|
||||
//
|
||||
caStatus verifyRequest ( casChannelI * & pChan );
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
caStatus uknownMessageAction ();
|
||||
caStatus eventAddAction ();
|
||||
caStatus eventCancelAction ();
|
||||
caStatus readAction ();
|
||||
caStatus readNotifyAction ();
|
||||
caStatus writeAction ();
|
||||
caStatus eventsOffAction ();
|
||||
caStatus eventsOnAction ();
|
||||
caStatus readSyncAction ();
|
||||
caStatus clearChannelAction ();
|
||||
caStatus claimChannelAction ();
|
||||
caStatus writeNotifyAction ();
|
||||
caStatus clientNameAction ();
|
||||
caStatus hostNameAction ();
|
||||
|
||||
//
|
||||
// accessRightsResponse()
|
||||
//
|
||||
caStatus accessRightsResponse (casChannelI *pciu);
|
||||
|
||||
//
|
||||
// these prepare the gdd based on what is in the ca hdr
|
||||
//
|
||||
caStatus read ( smartGDDPointer & pDesc );
|
||||
caStatus write ();
|
||||
|
||||
caStatus writeArrayData();
|
||||
caStatus writeScalarData();
|
||||
caStatus writeString();
|
||||
|
||||
//
|
||||
// io independent send/recv
|
||||
//
|
||||
outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT & nBytesSent );
|
||||
inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv,
|
||||
inBufClient::fillParameter parm, bufSizeT & nByesRecv );
|
||||
|
||||
virtual xBlockingStatus blockingState () const = 0;
|
||||
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT &nBytesActual ) = 0;
|
||||
|
||||
caStatus readNotifyFailureResponse ( const caHdrLargeArray & msg,
|
||||
const caStatus ECA_XXXX );
|
||||
|
||||
caStatus monitorFailureResponse ( const caHdrLargeArray & msg,
|
||||
const caStatus ECA_XXXX );
|
||||
|
||||
caStatus writeNotifyResponseECA_XXX ( const caHdrLargeArray &msg,
|
||||
const caStatus status );
|
||||
|
||||
caStatus casMonitorCallBack ( casMonitor &,
|
||||
const smartConstGDDPointer & pValue );
|
||||
|
||||
casStrmClient ( const casStrmClient & );
|
||||
casStrmClient & operator = ( const casStrmClient & );
|
||||
};
|
||||
|
||||
#endif // casStrmClienth
|
||||
|
||||
@@ -27,9 +27,10 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#include "alarm.h" // EPICS alarm severity/condition
|
||||
#include "errMdef.h" // EPICS error codes
|
||||
#include "gdd.h" // EPICS data descriptors
|
||||
#include "errMdef.h" // EPICS error codes
|
||||
#include "gdd.h" // EPICS data descriptors
|
||||
#include "smartGDDPointer.h" // auto ref gdd pointer
|
||||
#include "alarm.h" // EPICS alarm severity/condition
|
||||
|
||||
#ifdef epicsExportSharedSymbols_casdefh
|
||||
# define epicsExportSharedSymbols
|
||||
@@ -37,6 +38,7 @@
|
||||
#endif
|
||||
|
||||
#include "caNetAddr.h"
|
||||
#include "casEventMask.h" // EPICS event select class
|
||||
|
||||
typedef aitUint32 caStatus;
|
||||
|
||||
@@ -107,6 +109,10 @@ typedef aitUint32 caStatus;
|
||||
enum pvExistReturnEnum { pverExistsHere, pverDoesNotExistHere,
|
||||
pverAsyncCompletion };
|
||||
|
||||
class casPV;
|
||||
class casCtx;
|
||||
class casChannel;
|
||||
|
||||
class epicsShareClass pvExistReturn { // X aCC 361
|
||||
public:
|
||||
// most server tools will use this
|
||||
@@ -124,8 +130,6 @@ private:
|
||||
pvExistReturnEnum status;
|
||||
};
|
||||
|
||||
class casPV;
|
||||
|
||||
//
|
||||
// pvAttachReturn
|
||||
//
|
||||
@@ -143,17 +147,11 @@ private:
|
||||
caStatus stat;
|
||||
};
|
||||
|
||||
#include "casEventMask.h" // EPICS event select class
|
||||
#include "casInternal.h" // CA server private
|
||||
|
||||
class caServerI;
|
||||
|
||||
//
|
||||
// caServer - Channel Access Server API Class
|
||||
//
|
||||
class caServer {
|
||||
friend class casPVI;
|
||||
|
||||
public:
|
||||
epicsShareFunc caServer ();
|
||||
epicsShareFunc virtual ~caServer() = 0;
|
||||
@@ -231,30 +229,30 @@ public:
|
||||
// subset of named process variables at its privately specified date by
|
||||
// attaching to additional client private process variables.
|
||||
//
|
||||
epicsShareFunc virtual pvAttachReturn pvAttach (const casCtx &ctx,
|
||||
const char *pPVAliasName);
|
||||
epicsShareFunc virtual pvAttachReturn pvAttach ( const casCtx &ctx,
|
||||
const char *pPVAliasName );
|
||||
|
||||
//
|
||||
// obtain an event mask for a named event type
|
||||
// to be used with casPV::postEvent()
|
||||
//
|
||||
epicsShareFunc casEventMask registerEvent (const char *pName);
|
||||
epicsShareFunc casEventMask registerEvent ( const char *pName );
|
||||
|
||||
//
|
||||
// common event masks
|
||||
// (what is currently used by the CA clients)
|
||||
//
|
||||
epicsShareFunc casEventMask valueEventMask() const; // DBE_VALUE
|
||||
epicsShareFunc casEventMask logEventMask() const; // DBE_LOG
|
||||
epicsShareFunc casEventMask alarmEventMask() const; // DBE_ALARM
|
||||
epicsShareFunc casEventMask valueEventMask () const; // DBE_VALUE
|
||||
epicsShareFunc casEventMask logEventMask () const; // DBE_LOG
|
||||
epicsShareFunc casEventMask alarmEventMask () const; // DBE_ALARM
|
||||
|
||||
epicsShareFunc void setDebugLevel (unsigned level);
|
||||
epicsShareFunc void setDebugLevel ( unsigned level );
|
||||
epicsShareFunc unsigned getDebugLevel () const;
|
||||
|
||||
//
|
||||
// dump internal state of server to standard out
|
||||
//
|
||||
epicsShareFunc virtual void show (unsigned level) const;
|
||||
epicsShareFunc virtual void show ( unsigned level ) const;
|
||||
|
||||
//
|
||||
// server diagnostic counters (allowed to roll over)
|
||||
@@ -275,11 +273,11 @@ public:
|
||||
// caStatus disableClients ();
|
||||
|
||||
private:
|
||||
caServerI *pCAS;
|
||||
class caServerI * pCAS;
|
||||
|
||||
// deprecated interfaces (will be deleted in a future release)
|
||||
epicsShareFunc virtual class pvCreateReturn createPV ( const casCtx & ctx,
|
||||
const char *pPVAliasName);
|
||||
const char *pPVAliasName );
|
||||
};
|
||||
|
||||
//
|
||||
@@ -307,7 +305,7 @@ private:
|
||||
// then it may decide to provide a "destroy()" implementation in the
|
||||
// derived class which is a noop.
|
||||
//
|
||||
class casPV : private casPVI {
|
||||
class casPV {
|
||||
public:
|
||||
epicsShareFunc casPV ();
|
||||
|
||||
@@ -318,7 +316,7 @@ public:
|
||||
// caServer::show() is called and the level is high
|
||||
// enough
|
||||
//
|
||||
epicsShareFunc virtual void show (unsigned level) const;
|
||||
epicsShareFunc virtual void show ( unsigned level ) const;
|
||||
|
||||
//
|
||||
// called by the server libary each time that it wishes to
|
||||
@@ -406,7 +404,7 @@ public:
|
||||
// implements this function then it must create a casChannel object
|
||||
// (or a derived class) each time that this routine is called
|
||||
//
|
||||
epicsShareFunc virtual casChannel *createChannel (const casCtx &ctx,
|
||||
epicsShareFunc virtual casChannel * createChannel ( const casCtx &ctx,
|
||||
const char * const pUserName, const char * const pHostName);
|
||||
|
||||
//
|
||||
@@ -468,13 +466,13 @@ public:
|
||||
// set to one then the bound on the second dimension
|
||||
// are being fetched...
|
||||
//
|
||||
epicsShareFunc virtual unsigned maxDimension() const; // return zero if scalar
|
||||
epicsShareFunc virtual aitIndex maxBound (unsigned dimension) const;
|
||||
epicsShareFunc virtual unsigned maxDimension () const; // return zero if scalar
|
||||
epicsShareFunc virtual aitIndex maxBound ( unsigned dimension ) const;
|
||||
|
||||
//
|
||||
// Server tool calls this function to post a PV event.
|
||||
//
|
||||
epicsShareFunc void postEvent (const casEventMask &select, const gdd &event);
|
||||
epicsShareFunc void postEvent ( const casEventMask & select, const gdd & event );
|
||||
|
||||
//
|
||||
// peek at the pv name
|
||||
@@ -489,7 +487,7 @@ public:
|
||||
//
|
||||
// !! not thread safe !!
|
||||
//
|
||||
epicsShareFunc virtual const char *getName() const = 0;
|
||||
epicsShareFunc virtual const char * getName () const = 0;
|
||||
|
||||
//
|
||||
// Find the server associated with this PV
|
||||
@@ -501,18 +499,17 @@ public:
|
||||
// before the server
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc caServer *getCAS() const;
|
||||
epicsShareFunc caServer * getCAS () const;
|
||||
|
||||
//
|
||||
// only used when caStrmClient converts from
|
||||
// casPV * to casPVI *
|
||||
//
|
||||
friend class casStrmClient;
|
||||
//friend class casStrmClient;
|
||||
|
||||
|
||||
private:
|
||||
casPV *apiPointer (); //retruns NULL if casPVI isnt a base of casPV
|
||||
casPV ( const casPV & );
|
||||
casPVI * pPVI;
|
||||
friend class casPVI; // used ony to get casPVI casPV ( const casPV & );
|
||||
casPV & operator = ( const casPV & );
|
||||
|
||||
public:
|
||||
@@ -545,17 +542,17 @@ public:
|
||||
// client attachment to this channel (and reclaim any resources
|
||||
// allocated by the server library on its behalf)
|
||||
//
|
||||
class casChannel : private casPVListChan {
|
||||
class casChannel {
|
||||
public:
|
||||
epicsShareFunc casChannel (const casCtx &ctx);
|
||||
epicsShareFunc virtual ~casChannel();
|
||||
epicsShareFunc casChannel ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casChannel ();
|
||||
|
||||
//
|
||||
// Called when the user name and the host name are changed
|
||||
// for a live connection.
|
||||
//
|
||||
epicsShareFunc virtual void setOwner (const char * const pUserName,
|
||||
const char * const pHostName);
|
||||
epicsShareFunc virtual void setOwner ( const char * const pUserName,
|
||||
const char * const pHostName );
|
||||
|
||||
//
|
||||
// the following are encouraged to change during an channel's
|
||||
@@ -599,17 +596,13 @@ public:
|
||||
// for virtual casChannel::destroy()
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc casPV *getPV ();
|
||||
epicsShareFunc casPV * getPV ();
|
||||
|
||||
private:
|
||||
class casChannelI * pChanI;
|
||||
friend class casStrmClient; // used ony to get casChannelI
|
||||
casChannel ( const casChannel & );
|
||||
casChannel & operator = ( const casChannel & );
|
||||
|
||||
//
|
||||
// only used when casStrmClient converts between
|
||||
// casChannel * and casChannelI *
|
||||
//
|
||||
friend class casStrmClient;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -668,13 +661,13 @@ private:
|
||||
// in the destructor, for the class deriving from
|
||||
// casAsyncReadIO.
|
||||
// **
|
||||
class casAsyncReadIO : private casAsyncIOI {
|
||||
class casAsyncReadIO {
|
||||
public:
|
||||
|
||||
//
|
||||
// casAsyncReadIO()
|
||||
//
|
||||
epicsShareFunc casAsyncReadIO (const casCtx &ctx);
|
||||
epicsShareFunc casAsyncReadIO ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casAsyncReadIO ();
|
||||
|
||||
//
|
||||
@@ -683,7 +676,8 @@ public:
|
||||
//
|
||||
// only the first call to this function has any effect
|
||||
//
|
||||
epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn, const gdd &valueRead);
|
||||
epicsShareFunc caStatus postIOCompletion (
|
||||
caStatus completionStatusIn, const gdd & valueRead );
|
||||
|
||||
//
|
||||
// Find the server associated with this async IO
|
||||
@@ -692,8 +686,12 @@ public:
|
||||
// into a server
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc caServer *getCAS () const;
|
||||
epicsShareFunc caServer * getCAS () const;
|
||||
|
||||
void serverInitiatedDestroy ();
|
||||
|
||||
private:
|
||||
class casAsyncReadIOI * pAsyncReadIOI;
|
||||
//
|
||||
// called by the server lib after the response message
|
||||
// is succesfully queued to the client or when the
|
||||
@@ -703,15 +701,6 @@ public:
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
caHdrLargeArray const msg;
|
||||
casChannelI &chan;
|
||||
smartConstGDDPointer pDD;
|
||||
caStatus completionStatus;
|
||||
|
||||
epicsShareFunc bool readOP() const;
|
||||
epicsShareFunc caStatus cbFuncAsyncIO();
|
||||
|
||||
casAsyncReadIO ( const casAsyncReadIO & );
|
||||
casAsyncReadIO & operator = ( const casAsyncReadIO & );
|
||||
};
|
||||
@@ -731,12 +720,12 @@ private:
|
||||
// casAsyncWriteIO.
|
||||
// **
|
||||
//
|
||||
class casAsyncWriteIO : private casAsyncIOI {
|
||||
class casAsyncWriteIO {
|
||||
public:
|
||||
//
|
||||
// casAsyncWriteIO()
|
||||
//
|
||||
epicsShareFunc casAsyncWriteIO (const casCtx &ctx);
|
||||
epicsShareFunc casAsyncWriteIO ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casAsyncWriteIO ();
|
||||
|
||||
//
|
||||
@@ -744,7 +733,7 @@ public:
|
||||
// (this function does not delete the casAsyncWriteIO object).
|
||||
// Only the first call to this function has any effect.
|
||||
//
|
||||
epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn);
|
||||
epicsShareFunc caStatus postIOCompletion ( caStatus completionStatusIn );
|
||||
|
||||
//
|
||||
// Find the server associated with this async IO
|
||||
@@ -753,8 +742,12 @@ public:
|
||||
// into a server
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc caServer *getCAS () const;
|
||||
epicsShareFunc caServer * getCAS () const;
|
||||
|
||||
void serverInitiatedDestroy ();
|
||||
|
||||
private:
|
||||
class casAsyncWriteIOI * pAsyncWriteIOI;
|
||||
//
|
||||
// called by the server lib after the response message
|
||||
// is succesfully queued to the client or when the
|
||||
@@ -764,12 +757,6 @@ public:
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
caHdrLargeArray const msg;
|
||||
casChannelI &chan;
|
||||
caStatus completionStatus;
|
||||
|
||||
epicsShareFunc caStatus cbFuncAsyncIO ();
|
||||
casAsyncWriteIO ( const casAsyncWriteIO & );
|
||||
casAsyncWriteIO & operator = ( const casAsyncWriteIO & );
|
||||
};
|
||||
@@ -778,7 +765,7 @@ private:
|
||||
// casAsyncPVExistIO
|
||||
// - for use with caServer::pvExistTest()
|
||||
//
|
||||
class casAsyncPVExistIO : private casAsyncIOI {
|
||||
class casAsyncPVExistIO {
|
||||
public:
|
||||
|
||||
//
|
||||
@@ -802,7 +789,12 @@ public:
|
||||
// into a server
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc caServer * getCAS() const;
|
||||
epicsShareFunc caServer * getCAS () const;
|
||||
|
||||
void serverInitiatedDestroy ();
|
||||
|
||||
private:
|
||||
class casAsyncPVExistIOI * pAsyncPVExistIOI;
|
||||
|
||||
//
|
||||
// called by the server lib after the response message
|
||||
@@ -812,15 +804,7 @@ public:
|
||||
// default destroy executes a "delete this"
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
const caHdrLargeArray msg;
|
||||
pvExistReturn retVal;
|
||||
const caNetAddr dgOutAddr;
|
||||
const ca_uint16_t protocolRevision;
|
||||
const ca_uint32_t sequenceNumber;
|
||||
|
||||
epicsShareFunc caStatus cbFuncAsyncIO();
|
||||
|
||||
casAsyncPVExistIO ( const casAsyncPVExistIO & );
|
||||
casAsyncPVExistIO & operator = ( const casAsyncPVExistIO & );
|
||||
};
|
||||
@@ -829,12 +813,12 @@ private:
|
||||
// casAsyncPVAttachIO
|
||||
// - for use with caServer::pvAttach()
|
||||
//
|
||||
class casAsyncPVAttachIO : private casAsyncIOI {
|
||||
class casAsyncPVAttachIO {
|
||||
public:
|
||||
//
|
||||
// casAsyncPVAttachIO()
|
||||
//
|
||||
epicsShareFunc casAsyncPVAttachIO (const casCtx &ctx);
|
||||
epicsShareFunc casAsyncPVAttachIO ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casAsyncPVAttachIO ();
|
||||
|
||||
//
|
||||
@@ -842,7 +826,7 @@ public:
|
||||
// (this function does not delete the casAsyncPVAttachIO object).
|
||||
// Only the first call to this function has any effect.
|
||||
//
|
||||
epicsShareFunc caStatus postIOCompletion (const pvAttachReturn &retValIn);
|
||||
epicsShareFunc caStatus postIOCompletion ( const pvAttachReturn & retValIn );
|
||||
|
||||
//
|
||||
// Find the server associated with this async IO
|
||||
@@ -851,7 +835,12 @@ public:
|
||||
// into a server
|
||||
// ***************
|
||||
//
|
||||
epicsShareFunc caServer *getCAS() const;
|
||||
epicsShareFunc caServer * getCAS () const;
|
||||
|
||||
void serverInitiatedDestroy ();
|
||||
|
||||
private:
|
||||
class casAsyncPVAttachIOI * pAsyncPVAttachIOI;
|
||||
|
||||
//
|
||||
// called by the server lib after the response message
|
||||
@@ -862,11 +851,6 @@ public:
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
caHdrLargeArray const msg;
|
||||
pvAttachReturn retVal;
|
||||
|
||||
epicsShareFunc caStatus cbFuncAsyncIO ();
|
||||
casAsyncPVAttachIO ( const casAsyncPVAttachIO & );
|
||||
casAsyncPVAttachIO & operator = ( const casAsyncPVAttachIO & );
|
||||
};
|
||||
@@ -877,8 +861,8 @@ private:
|
||||
//
|
||||
class casAsyncPVCreateIO : private casAsyncPVAttachIO {
|
||||
public:
|
||||
epicsShareFunc casAsyncPVCreateIO(const casCtx &ctx);
|
||||
epicsShareFunc virtual ~casAsyncPVCreateIO();
|
||||
epicsShareFunc casAsyncPVCreateIO ( const casCtx & ctx );
|
||||
epicsShareFunc virtual ~casAsyncPVCreateIO ();
|
||||
private:
|
||||
casAsyncPVCreateIO ( const casAsyncPVCreateIO & );
|
||||
casAsyncPVCreateIO & operator = ( const casAsyncPVCreateIO & );
|
||||
@@ -890,8 +874,8 @@ private:
|
||||
//
|
||||
class epicsShareClass pvCreateReturn : public pvAttachReturn {
|
||||
public:
|
||||
pvCreateReturn (caStatus statIn) : pvAttachReturn(statIn) {};
|
||||
pvCreateReturn (casPV &pvIn) : pvAttachReturn (pvIn) {};
|
||||
pvCreateReturn ( caStatus statIn ) : pvAttachReturn ( statIn ) {};
|
||||
pvCreateReturn ( casPV & pvIn ) : pvAttachReturn ( pvIn ) {};
|
||||
};
|
||||
|
||||
// TODO:
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "clientBufMemoryManager.h"
|
||||
|
||||
bufSizeT clientBufMemoryManager::maxSize () const
|
||||
{
|
||||
|
||||
50
src/cas/generic/clientBufMemoryManager.h
Normal file
50
src/cas/generic/clientBufMemoryManager.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef clientBufMemoryManagerh
|
||||
#define clientBufMemoryManagerh
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
typedef unsigned bufSizeT;
|
||||
static const unsigned bufSizeT_MAX = UINT_MAX;
|
||||
|
||||
class casBufferFactory {
|
||||
public:
|
||||
casBufferFactory ();
|
||||
~casBufferFactory ();
|
||||
unsigned smallBufferSize () const;
|
||||
char * newSmallBuffer ();
|
||||
void destroySmallBuffer ( char * pBuf );
|
||||
unsigned largeBufferSize () const;
|
||||
char * newLargeBuffer ();
|
||||
void destroyLargeBuffer ( char * pBuf );
|
||||
private:
|
||||
void * smallBufFreeList;
|
||||
void * largeBufFreeList;
|
||||
unsigned largeBufferSizePriv;
|
||||
};
|
||||
|
||||
struct casBufferParm {
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
};
|
||||
|
||||
class clientBufMemoryManager {
|
||||
public:
|
||||
casBufferParm allocate ( bufSizeT newMinSize );
|
||||
void release ( char * pBuf, bufSizeT bufSize );
|
||||
bufSizeT maxSize () const;
|
||||
private:
|
||||
casBufferFactory bufferFactory;
|
||||
};
|
||||
|
||||
#endif // clientBufMemoryManagerh
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "inBufIL.h" // inBuf in line func
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "inBuf.h"
|
||||
|
||||
//
|
||||
// inBuf::inBuf()
|
||||
|
||||
170
src/cas/generic/inBuf.h
Normal file
170
src/cas/generic/inBuf.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef inBufh
|
||||
#define inBufh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_inBufh
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#undef epicsAssertAuthor
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "epicsAssert.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_inBufh
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#include "clientBufMemoryManager.h"
|
||||
|
||||
class inBufCtx {
|
||||
friend class inBuf;
|
||||
public:
|
||||
enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess };
|
||||
inBufCtx ( const inBuf & ); // success
|
||||
inBufCtx (); // failure
|
||||
|
||||
pushCtxResult pushResult () const;
|
||||
|
||||
private:
|
||||
pushCtxResult stat;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT bytesInBuffer;
|
||||
bufSizeT nextReadIndex;
|
||||
};
|
||||
|
||||
class inBufClient { // X aCC 655
|
||||
public:
|
||||
enum fillCondition { casFillNone, casFillProgress,
|
||||
casFillDisconnect };
|
||||
// this is a hack for a Solaris IP kernel feature
|
||||
enum fillParameter { fpNone, fpUseBroadcastInterface };
|
||||
virtual unsigned getDebugLevel () const = 0;
|
||||
virtual bufSizeT incomingBytesPresent () const = 0;
|
||||
virtual fillCondition xRecv ( char *pBuf, bufSizeT nBytesToRecv,
|
||||
enum fillParameter parm, bufSizeT &nByesRecv ) = 0;
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
};
|
||||
|
||||
class inBuf {
|
||||
friend class inBufCtx;
|
||||
public:
|
||||
inBuf ( class inBufClient &, class clientBufMemoryManager &,
|
||||
bufSizeT ioMinSizeIn );
|
||||
virtual ~inBuf ();
|
||||
bufSizeT bytesPresent () const;
|
||||
bufSizeT bytesAvailable () const;
|
||||
bool full () const;
|
||||
inBufClient::fillCondition fill (
|
||||
inBufClient::fillParameter parm = inBufClient::fpNone );
|
||||
void show ( unsigned level ) const;
|
||||
void removeMsg ( bufSizeT nBytes );
|
||||
char * msgPtr () const;
|
||||
//
|
||||
// This is used to create recursive protocol stacks. A subsegment
|
||||
// of the buffer of max size "maxSize" is assigned to the next
|
||||
// layer down in the protocol stack by pushCtx () until popCtx ()
|
||||
// is called. The roiutine popCtx () returns the actual number
|
||||
// of bytes used by the next layer down.
|
||||
//
|
||||
// pushCtx() returns an outBufCtx to be restored by popCtx()
|
||||
//
|
||||
const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize );
|
||||
bufSizeT popCtx ( const inBufCtx & ); // returns actual size
|
||||
unsigned bufferSize () const;
|
||||
void expandBuffer ();
|
||||
private:
|
||||
class inBufClient & client;
|
||||
class clientBufMemoryManager & memMgr;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT bytesInBuffer;
|
||||
bufSizeT nextReadIndex;
|
||||
bufSizeT ioMinSize;
|
||||
unsigned ctxRecursCount;
|
||||
inBuf ( const inBuf & );
|
||||
inBuf & operator = ( const inBuf & );
|
||||
};
|
||||
|
||||
//
|
||||
// inBuf::bytesPresent()
|
||||
//
|
||||
inline bufSizeT inBuf::bytesPresent () const
|
||||
{
|
||||
return this->bytesInBuffer-this->nextReadIndex;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::bytesAvailable()
|
||||
//
|
||||
inline bufSizeT inBuf::bytesAvailable () const
|
||||
{
|
||||
bufSizeT bp;
|
||||
bp = this->bytesPresent ();
|
||||
bp += this->client.incomingBytesPresent ();
|
||||
return bp;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::full()
|
||||
//
|
||||
inline bool inBuf::full () const
|
||||
{
|
||||
if (this->bufSize-this->bytesPresent()<this->ioMinSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::msgPtr()
|
||||
//
|
||||
inline char *inBuf::msgPtr () const
|
||||
{
|
||||
return &this->pBuf[this->nextReadIndex];
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::removeMsg()
|
||||
//
|
||||
inline void inBuf::removeMsg ( bufSizeT nBytes )
|
||||
{
|
||||
this->nextReadIndex += nBytes;
|
||||
assert ( this->nextReadIndex <= this->bytesInBuffer );
|
||||
}
|
||||
|
||||
//
|
||||
// inBufCtx::inBufCtx ()
|
||||
//
|
||||
inline inBufCtx::inBufCtx () :
|
||||
stat (pushCtxNoSpace) {}
|
||||
|
||||
//
|
||||
// inBufCtx::inBufCtx ()
|
||||
//
|
||||
inline inBufCtx::inBufCtx (const inBuf &inBufIn) :
|
||||
stat (pushCtxSuccess), pBuf (inBufIn.pBuf),
|
||||
bufSize (inBufIn.bufSize), bytesInBuffer (inBufIn.bytesInBuffer),
|
||||
nextReadIndex (inBufIn.nextReadIndex) {}
|
||||
|
||||
//
|
||||
// inBufCtx::pushResult
|
||||
//
|
||||
inline inBufCtx::pushCtxResult inBufCtx::pushResult () const
|
||||
{
|
||||
return this->stat;
|
||||
}
|
||||
|
||||
#endif // inBufh
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef inBufILh
|
||||
#define inBufILh
|
||||
|
||||
//
|
||||
// inBuf::bytesPresent()
|
||||
//
|
||||
inline bufSizeT inBuf::bytesPresent () const
|
||||
{
|
||||
return this->bytesInBuffer-this->nextReadIndex;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::bytesAvailable()
|
||||
//
|
||||
inline bufSizeT inBuf::bytesAvailable () const
|
||||
{
|
||||
bufSizeT bp;
|
||||
bp = this->bytesPresent ();
|
||||
bp += this->client.incomingBytesPresent ();
|
||||
return bp;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::full()
|
||||
//
|
||||
inline bool inBuf::full () const
|
||||
{
|
||||
if (this->bufSize-this->bytesPresent()<this->ioMinSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::msgPtr()
|
||||
//
|
||||
inline char *inBuf::msgPtr () const
|
||||
{
|
||||
return &this->pBuf[this->nextReadIndex];
|
||||
}
|
||||
|
||||
//
|
||||
// inBuf::removeMsg()
|
||||
//
|
||||
inline void inBuf::removeMsg ( bufSizeT nBytes )
|
||||
{
|
||||
this->nextReadIndex += nBytes;
|
||||
assert ( this->nextReadIndex <= this->bytesInBuffer );
|
||||
}
|
||||
|
||||
//
|
||||
// inBufCtx::inBufCtx ()
|
||||
//
|
||||
inline inBufCtx::inBufCtx () :
|
||||
stat (pushCtxNoSpace) {}
|
||||
|
||||
//
|
||||
// inBufCtx::inBufCtx ()
|
||||
//
|
||||
inline inBufCtx::inBufCtx (const inBuf &inBufIn) :
|
||||
stat (pushCtxSuccess), pBuf (inBufIn.pBuf),
|
||||
bufSize (inBufIn.bufSize), bytesInBuffer (inBufIn.bytesInBuffer),
|
||||
nextReadIndex (inBufIn.nextReadIndex) {}
|
||||
|
||||
//
|
||||
// inBufCtx::pushResult
|
||||
//
|
||||
inline inBufCtx::pushCtxResult inBufCtx::pushResult () const
|
||||
{
|
||||
return this->stat;
|
||||
}
|
||||
|
||||
#endif // inBufILh
|
||||
|
||||
56
src/cas/generic/ioBlocked.h
Normal file
56
src/cas/generic/ioBlocked.h
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef ioBlockedh
|
||||
#define ioBlockedh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_ioBlockedh
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include "tsDLList.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_ioBlockedh
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
class ioBlocked : public tsDLNode < ioBlocked > {
|
||||
friend class ioBlockedList;
|
||||
public:
|
||||
ioBlocked ();
|
||||
virtual ~ioBlocked ();
|
||||
private:
|
||||
ioBlockedList * pList;
|
||||
virtual void ioBlockedSignal ();
|
||||
};
|
||||
|
||||
class ioBlockedList : private tsDLList<ioBlocked> {
|
||||
friend class ioBlocked;
|
||||
public:
|
||||
ioBlockedList ();
|
||||
virtual ~ioBlockedList ();
|
||||
void signal ();
|
||||
void addItemToIOBLockedList ( ioBlocked & item );
|
||||
ioBlockedList ( const ioBlockedList & );
|
||||
ioBlockedList & operator = ( const ioBlockedList & );
|
||||
};
|
||||
|
||||
#endif // ioBlockedh
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
|
||||
|
||||
//
|
||||
// ioBlocked::~ioBlocked()
|
||||
//
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "outBufIL.h" // outBuf in line func
|
||||
#define epicsExportSharedSymbols
|
||||
#include "outBuf.h"
|
||||
#include "osiWireFormat.h"
|
||||
|
||||
//
|
||||
|
||||
169
src/cas/generic/outBuf.h
Normal file
169
src/cas/generic/outBuf.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef outBufh
|
||||
#define outBufh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols_outBufh
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include "caProto.h"
|
||||
|
||||
#ifdef epicsExportSharedSymbols_outBufh
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#include "casdef.h"
|
||||
#include "clientBufMemoryManager.h"
|
||||
|
||||
//
|
||||
// outBufCtx
|
||||
//
|
||||
class outBufCtx {
|
||||
friend class outBuf;
|
||||
public:
|
||||
enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess };
|
||||
outBufCtx ( const outBuf & ); // success
|
||||
outBufCtx (); // failure
|
||||
|
||||
pushCtxResult pushResult () const;
|
||||
|
||||
private:
|
||||
pushCtxResult stat;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT stack;
|
||||
};
|
||||
|
||||
class outBufClient { // X aCC 655
|
||||
public:
|
||||
enum flushCondition { flushNone, flushProgress, flushDisconnect };
|
||||
virtual unsigned getDebugLevel () const = 0;
|
||||
virtual void sendBlockSignal () = 0;
|
||||
virtual flushCondition xSend ( char *pBuf, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ) = 0;
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// outBuf
|
||||
//
|
||||
class outBuf {
|
||||
friend class outBufCtx;
|
||||
public:
|
||||
outBuf ( outBufClient &, clientBufMemoryManager & );
|
||||
virtual ~outBuf ();
|
||||
|
||||
bufSizeT bytesPresent () const;
|
||||
|
||||
//
|
||||
// flush output queue
|
||||
// (returns the number of bytes sent)
|
||||
//
|
||||
outBufClient::flushCondition flush ( bufSizeT spaceRequired=bufSizeT_MAX );
|
||||
|
||||
void show (unsigned level) const;
|
||||
|
||||
unsigned bufferSize () const;
|
||||
|
||||
//
|
||||
// allocate message buffer space
|
||||
// (leaves message buffer locked)
|
||||
//
|
||||
caStatus copyInHeader ( ca_uint16_t response, ca_uint32_t payloadSize,
|
||||
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
|
||||
ca_uint32_t responseSpecific, void **pPayload );
|
||||
|
||||
//
|
||||
// commit message created with copyInHeader
|
||||
//
|
||||
void commitMsg ();
|
||||
void commitMsg ( ca_uint32_t reducedPayloadSize );
|
||||
|
||||
caStatus allocRawMsg ( bufSizeT msgsize, void **ppMsg );
|
||||
void commitRawMsg ( bufSizeT size );
|
||||
|
||||
//
|
||||
// This is used to create recursive protocol stacks. A subsegment
|
||||
// of the buffer of max size "maxSize" is assigned to the next
|
||||
// layer down in the protocol stack by pushCtx () until popCtx ()
|
||||
// is called. The routine popCtx () returns the actual number
|
||||
// of bytes used by the next layer down.
|
||||
//
|
||||
// pushCtx() returns an outBufCtx to be restored by popCtx()
|
||||
//
|
||||
const outBufCtx pushCtx ( bufSizeT headerSize,
|
||||
bufSizeT maxBodySize, void *&pHeader );
|
||||
bufSizeT popCtx ( const outBufCtx & ); // returns actual size
|
||||
|
||||
private:
|
||||
outBufClient & client;
|
||||
clientBufMemoryManager & memMgr;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT stack;
|
||||
unsigned ctxRecursCount;
|
||||
|
||||
void expandBuffer ();
|
||||
|
||||
outBuf ( const outBuf & );
|
||||
outBuf & operator = ( const outBuf & );
|
||||
};
|
||||
|
||||
//
|
||||
// outBuf::bytesPresent ()
|
||||
// number of bytes in the output queue
|
||||
//
|
||||
inline bufSizeT outBuf::bytesPresent () const
|
||||
{
|
||||
//
|
||||
// Note on use of lock here:
|
||||
// This guarantees that any pushCtx() operation
|
||||
// in progress completes before another thread checks.
|
||||
//
|
||||
bufSizeT result = this->stack;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// outBuf::commitRawMsg()
|
||||
//
|
||||
inline void outBuf::commitRawMsg (bufSizeT size)
|
||||
{
|
||||
this->stack += size;
|
||||
assert ( this->stack <= this->bufSize );
|
||||
}
|
||||
|
||||
//
|
||||
// outBufCtx::outBufCtx ()
|
||||
//
|
||||
inline outBufCtx::outBufCtx () :
|
||||
stat (pushCtxNoSpace) {}
|
||||
|
||||
//
|
||||
// outBufCtx::outBufCtx ()
|
||||
//
|
||||
inline outBufCtx::outBufCtx (const outBuf &outBufIn) :
|
||||
stat (pushCtxSuccess), pBuf (outBufIn.pBuf),
|
||||
bufSize (outBufIn.bufSize), stack (outBufIn.stack) {}
|
||||
|
||||
//
|
||||
// outBufCtx::pushResult
|
||||
//
|
||||
inline outBufCtx::pushCtxResult outBufCtx::pushResult () const
|
||||
{
|
||||
return this->stat;
|
||||
}
|
||||
|
||||
#endif // outBufh
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef outBufILh
|
||||
#define outBufILh
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
#define outBufILh_epicsExportSharedSymbols
|
||||
#undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include "epicsGuard.h"
|
||||
|
||||
#ifdef outBufILh_epicsExportSharedSymbols
|
||||
#define epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
//
|
||||
// outBuf::bytesPresent ()
|
||||
// number of bytes in the output queue
|
||||
//
|
||||
inline bufSizeT outBuf::bytesPresent () const
|
||||
{
|
||||
//
|
||||
// Note on use of lock here:
|
||||
// This guarantees that any pushCtx() operation
|
||||
// in progress completes before another thread checks.
|
||||
//
|
||||
bufSizeT result = this->stack;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// outBuf::commitRawMsg()
|
||||
//
|
||||
inline void outBuf::commitRawMsg (bufSizeT size)
|
||||
{
|
||||
this->stack += size;
|
||||
assert ( this->stack <= this->bufSize );
|
||||
}
|
||||
|
||||
//
|
||||
// outBufCtx::outBufCtx ()
|
||||
//
|
||||
inline outBufCtx::outBufCtx () :
|
||||
stat (pushCtxNoSpace) {}
|
||||
|
||||
//
|
||||
// outBufCtx::outBufCtx ()
|
||||
//
|
||||
inline outBufCtx::outBufCtx (const outBuf &outBufIn) :
|
||||
stat (pushCtxSuccess), pBuf (outBufIn.pBuf),
|
||||
bufSize (outBufIn.bufSize), stack (outBufIn.stack) {}
|
||||
|
||||
//
|
||||
// outBufCtx::pushResult
|
||||
//
|
||||
inline outBufCtx::pushCtxResult outBufCtx::pushResult () const
|
||||
{
|
||||
return this->stat;
|
||||
}
|
||||
|
||||
#endif // outBufILh
|
||||
|
||||
@@ -1,974 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef INCLserverh
|
||||
#define INCLserverh
|
||||
|
||||
//
|
||||
// ANSI C
|
||||
//
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(epicsExportSharedSymbols)
|
||||
# error suspect that libCom, ca, and gdd were not imported
|
||||
#endif
|
||||
|
||||
//
|
||||
// EPICS
|
||||
// (some of these are included from casdef.h but
|
||||
// are included first here so that they are included
|
||||
// once only before epicsExportSharedSymbols is defined)
|
||||
//
|
||||
#include "gdd.h" // EPICS data descriptors
|
||||
#undef epicsAssertAuthor
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "epicsAssert.h" // EPICS assert() macros
|
||||
#include "epicsTime.h" // EPICS os independent time
|
||||
#include "alarm.h" // EPICS alarm severity/condition
|
||||
#include "errMdef.h" // EPICS error codes
|
||||
#include "resourceLib.h" // EPICS hashing templates
|
||||
#include "errlog.h" // EPICS error logging interface
|
||||
|
||||
//
|
||||
// CA
|
||||
//
|
||||
#include "caCommonDef.h"
|
||||
#include "caerr.h"
|
||||
|
||||
#if defined ( epicsExportSharedSymbols )
|
||||
# error suspect that libCom, ca, cxxTemplates, and gdd were not imported
|
||||
#endif
|
||||
|
||||
//
|
||||
// CAS
|
||||
//
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h" // sets proper def for shareLib.h defines
|
||||
#include "epicsMutex.h"
|
||||
void casVerifyFunc(const char *pFile, unsigned line, const char *pExp);
|
||||
void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment);
|
||||
#define serverToolDebug(COMMENT) \
|
||||
{serverToolDebugFunc(__FILE__, __LINE__, COMMENT); }
|
||||
#define casVerify(EXP) {if ((EXP)==0) casVerifyFunc(__FILE__, __LINE__, #EXP); }
|
||||
caStatus copyBetweenDD(gdd &dest, gdd &src);
|
||||
|
||||
enum xBlockingStatus {xIsBlocking, xIsntBlocking};
|
||||
enum casIOState {casOnLine, casOffLine};
|
||||
typedef unsigned bufSizeT;
|
||||
static const unsigned bufSizeT_MAX = UINT_MAX;
|
||||
|
||||
enum casProcCond {casProcOk, casProcDisconnect};
|
||||
|
||||
/*
|
||||
* maximum peak log entries for each event block (registartion)
|
||||
* (events cached into the last queue entry if over flow occurs)
|
||||
* (if this exceeds 256 then the casMonitor::nPend must
|
||||
* be assigned a new data type)
|
||||
*/
|
||||
#define individualEventEntries 16u
|
||||
|
||||
/*
|
||||
* maximum average log entries for each event block (registartion)
|
||||
* (events cached into the last queue entry if over flow occurs)
|
||||
* (if this exceeds 256 then the casMonitor::nPend must
|
||||
* be assigned a new data type)
|
||||
*/
|
||||
#define averageEventEntries 4u
|
||||
|
||||
typedef caResId caEventId;
|
||||
|
||||
//
|
||||
// fwd ref
|
||||
//
|
||||
class caServerI;
|
||||
|
||||
class casCtx {
|
||||
public:
|
||||
casCtx();
|
||||
|
||||
//
|
||||
// get
|
||||
//
|
||||
const caHdrLargeArray * getMsg () const;
|
||||
void * getData () const;
|
||||
caServerI * getServer () const;
|
||||
casCoreClient * getClient () const;
|
||||
casPVI * getPV () const;
|
||||
casChannelI * getChannel () const;
|
||||
|
||||
void setMsg ( const caHdrLargeArray &, void * pBody );
|
||||
|
||||
void setServer ( caServerI * p );
|
||||
|
||||
void setClient ( casCoreClient * p );
|
||||
|
||||
void setPV ( casPVI * p );
|
||||
|
||||
void setChannel ( casChannelI * p );
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
private:
|
||||
caHdrLargeArray msg; // ca message header
|
||||
void * pData; // pointer to data following header
|
||||
caServerI * pCAS;
|
||||
casCoreClient * pClient;
|
||||
casChannelI * pChannel;
|
||||
casPVI * pPV;
|
||||
unsigned nAsyncIO; // checks for improper use of async io
|
||||
};
|
||||
|
||||
//
|
||||
// inBufCtx
|
||||
//
|
||||
class inBufCtx {
|
||||
friend class inBuf;
|
||||
public:
|
||||
enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess };
|
||||
inBufCtx ( const inBuf & ); // success
|
||||
inBufCtx (); // failure
|
||||
|
||||
pushCtxResult pushResult () const;
|
||||
|
||||
private:
|
||||
pushCtxResult stat;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT bytesInBuffer;
|
||||
bufSizeT nextReadIndex;
|
||||
};
|
||||
|
||||
class casBufferFactory {
|
||||
public:
|
||||
casBufferFactory ();
|
||||
~casBufferFactory ();
|
||||
unsigned smallBufferSize () const;
|
||||
char * newSmallBuffer ();
|
||||
void destroySmallBuffer ( char * pBuf );
|
||||
unsigned largeBufferSize () const;
|
||||
char * newLargeBuffer ();
|
||||
void destroyLargeBuffer ( char * pBuf );
|
||||
private:
|
||||
void * smallBufFreeList;
|
||||
void * largeBufFreeList;
|
||||
unsigned largeBufferSizePriv;
|
||||
};
|
||||
|
||||
struct casBufferParm {
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
};
|
||||
|
||||
class clientBufMemoryManager {
|
||||
public:
|
||||
casBufferParm allocate ( bufSizeT newMinSize );
|
||||
void release ( char * pBuf, bufSizeT bufSize );
|
||||
bufSizeT maxSize () const;
|
||||
private:
|
||||
casBufferFactory bufferFactory;
|
||||
};
|
||||
|
||||
class inBufClient { // X aCC 655
|
||||
public:
|
||||
enum fillCondition { casFillNone, casFillProgress,
|
||||
casFillDisconnect };
|
||||
// this is a hack for a Solaris IP kernel feature
|
||||
enum fillParameter { fpNone, fpUseBroadcastInterface };
|
||||
virtual unsigned getDebugLevel () const = 0;
|
||||
virtual bufSizeT incomingBytesPresent () const = 0;
|
||||
virtual fillCondition xRecv ( char *pBuf, bufSizeT nBytesToRecv,
|
||||
enum fillParameter parm, bufSizeT &nByesRecv ) = 0;
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// inBuf
|
||||
//
|
||||
class inBuf {
|
||||
friend class inBufCtx;
|
||||
public:
|
||||
|
||||
inBuf ( inBufClient &, clientBufMemoryManager &,
|
||||
bufSizeT ioMinSizeIn );
|
||||
virtual ~inBuf ();
|
||||
|
||||
bufSizeT bytesPresent () const;
|
||||
|
||||
bufSizeT bytesAvailable () const;
|
||||
|
||||
bool full () const;
|
||||
|
||||
//
|
||||
// fill the input buffer with any incoming messages
|
||||
//
|
||||
inBufClient::fillCondition fill (
|
||||
inBufClient::fillParameter parm = inBufClient::fpNone );
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
void removeMsg ( bufSizeT nBytes );
|
||||
|
||||
char * msgPtr () const;
|
||||
|
||||
//
|
||||
// This is used to create recursive protocol stacks. A subsegment
|
||||
// of the buffer of max size "maxSize" is assigned to the next
|
||||
// layer down in the protocol stack by pushCtx () until popCtx ()
|
||||
// is called. The roiutine popCtx () returns the actual number
|
||||
// of bytes used by the next layer down.
|
||||
//
|
||||
// pushCtx() returns an outBufCtx to be restored by popCtx()
|
||||
//
|
||||
const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize );
|
||||
bufSizeT popCtx ( const inBufCtx & ); // returns actual size
|
||||
|
||||
unsigned bufferSize () const;
|
||||
|
||||
void expandBuffer ();
|
||||
|
||||
private:
|
||||
inBufClient & client;
|
||||
clientBufMemoryManager & memMgr;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT bytesInBuffer;
|
||||
bufSizeT nextReadIndex;
|
||||
bufSizeT ioMinSize;
|
||||
unsigned ctxRecursCount;
|
||||
inBuf ( const inBuf & );
|
||||
inBuf & operator = ( const inBuf & );
|
||||
};
|
||||
|
||||
//
|
||||
// outBufCtx
|
||||
//
|
||||
class outBufCtx {
|
||||
friend class outBuf;
|
||||
public:
|
||||
enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess };
|
||||
outBufCtx ( const outBuf & ); // success
|
||||
outBufCtx (); // failure
|
||||
|
||||
pushCtxResult pushResult () const;
|
||||
|
||||
private:
|
||||
pushCtxResult stat;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT stack;
|
||||
};
|
||||
|
||||
class outBufClient { // X aCC 655
|
||||
public:
|
||||
enum flushCondition { flushNone, flushProgress, flushDisconnect };
|
||||
virtual unsigned getDebugLevel () const = 0;
|
||||
virtual void sendBlockSignal () = 0;
|
||||
virtual flushCondition xSend ( char *pBuf, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ) = 0;
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// outBuf
|
||||
//
|
||||
class outBuf {
|
||||
friend class outBufCtx;
|
||||
public:
|
||||
|
||||
outBuf ( outBufClient &, clientBufMemoryManager & );
|
||||
virtual ~outBuf ();
|
||||
|
||||
bufSizeT bytesPresent () const;
|
||||
|
||||
//
|
||||
// flush output queue
|
||||
// (returns the number of bytes sent)
|
||||
//
|
||||
outBufClient::flushCondition flush ( bufSizeT spaceRequired=bufSizeT_MAX );
|
||||
|
||||
void show (unsigned level) const;
|
||||
|
||||
unsigned bufferSize () const;
|
||||
|
||||
//
|
||||
// allocate message buffer space
|
||||
// (leaves message buffer locked)
|
||||
//
|
||||
caStatus copyInHeader ( ca_uint16_t response, ca_uint32_t payloadSize,
|
||||
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
|
||||
ca_uint32_t responseSpecific, void **pPayload );
|
||||
|
||||
//
|
||||
// commit message created with copyInHeader
|
||||
//
|
||||
void commitMsg ();
|
||||
void commitMsg ( ca_uint32_t reducedPayloadSize );
|
||||
|
||||
caStatus allocRawMsg ( bufSizeT msgsize, void **ppMsg );
|
||||
void commitRawMsg ( bufSizeT size );
|
||||
|
||||
//
|
||||
// This is used to create recursive protocol stacks. A subsegment
|
||||
// of the buffer of max size "maxSize" is assigned to the next
|
||||
// layer down in the protocol stack by pushCtx () until popCtx ()
|
||||
// is called. The roiutine popCtx () returns the actual number
|
||||
// of bytes used by the next layer down.
|
||||
//
|
||||
// pushCtx() returns an outBufCtx to be restored by popCtx()
|
||||
//
|
||||
const outBufCtx pushCtx ( bufSizeT headerSize, bufSizeT maxBodySize, void *&pHeader );
|
||||
bufSizeT popCtx ( const outBufCtx & ); // returns actual size
|
||||
|
||||
private:
|
||||
outBufClient & client;
|
||||
clientBufMemoryManager & memMgr;
|
||||
char * pBuf;
|
||||
bufSizeT bufSize;
|
||||
bufSizeT stack;
|
||||
unsigned ctxRecursCount;
|
||||
|
||||
void expandBuffer ();
|
||||
|
||||
outBuf ( const outBuf & );
|
||||
outBuf & operator = ( const outBuf & );
|
||||
};
|
||||
|
||||
//
|
||||
// casEventSys
|
||||
//
|
||||
class casEventSys {
|
||||
public:
|
||||
casEventSys ( casCoreClient & );
|
||||
~casEventSys ();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
struct processStatus {
|
||||
casProcCond cond;
|
||||
unsigned nAccepted;
|
||||
};
|
||||
processStatus process ();
|
||||
|
||||
void installMonitor ();
|
||||
void removeMonitor ();
|
||||
|
||||
void removeFromEventQueue ( casEvent & );
|
||||
void addToEventQueue ( casEvent & );
|
||||
|
||||
void insertEventQueue ( casEvent & insert, casEvent & prevEvent );
|
||||
void pushOnToEventQueue ( casEvent & event );
|
||||
|
||||
bool full ();
|
||||
|
||||
bool getNDuplicateEvents () const;
|
||||
|
||||
void setDestroyPending ();
|
||||
|
||||
void eventsOn ();
|
||||
void eventsOff ();
|
||||
|
||||
private:
|
||||
tsDLList < casEvent > eventLogQue;
|
||||
casCoreClient & client;
|
||||
class casEventPurgeEv * pPurgeEvent; // flow control purge complete event
|
||||
unsigned numEventBlocks; // N event blocks installed
|
||||
unsigned maxLogEntries; // max log entries
|
||||
bool destroyPending;
|
||||
bool replaceEvents; // replace last existing event on queue
|
||||
bool dontProcess; // flow ctl is on - dont process event queue
|
||||
|
||||
casEventSys ( const casEventSys & );
|
||||
casEventSys & operator = ( const casEventSys & );
|
||||
friend class casEventPurgeEv;
|
||||
};
|
||||
|
||||
/*
|
||||
* when this event reaches the top of the queue we
|
||||
* know that all duplicate events have been purged
|
||||
* and that now no events should not be sent to the
|
||||
* client until it exits flow control mode
|
||||
*/
|
||||
class casEventPurgeEv : public casEvent {
|
||||
public:
|
||||
casEventPurgeEv ( class casEventSys & );
|
||||
private:
|
||||
casEventSys & evSys;
|
||||
caStatus cbFunc ( casCoreClient & );
|
||||
void eventSysDestroyNotify ( casCoreClient & );
|
||||
};
|
||||
|
||||
//
|
||||
// casCoreClient
|
||||
// (this will eventually support direct communication
|
||||
// between the client lib and the server lib)
|
||||
//
|
||||
class casCoreClient : public ioBlocked,
|
||||
private casMonitorCallbackInterface {
|
||||
public:
|
||||
casCoreClient ( caServerI & serverInternal );
|
||||
virtual ~casCoreClient ();
|
||||
virtual caStatus disconnectChan( caResId id );
|
||||
virtual void show ( unsigned level ) const;
|
||||
virtual void installChannel ( casChannelI & );
|
||||
virtual void removeChannel ( casChannelI & );
|
||||
|
||||
void installAsyncIO ( casAsyncIOI & ioIn );
|
||||
void removeAsyncIO ( casAsyncIOI & ioIn );
|
||||
void installChannelsAsynchIO (
|
||||
tsDLList < casAsyncIOI > & list, casAsyncIOI & io );
|
||||
void uninstallChannelsAsynchIO (
|
||||
tsDLList < casAsyncIOI > & list, casAsyncIOI & io );
|
||||
|
||||
caServerI & getCAS () const;
|
||||
|
||||
//
|
||||
// one virtual function for each CA request type that has
|
||||
// asynchronous completion
|
||||
//
|
||||
virtual caStatus asyncSearchResponse (
|
||||
const caNetAddr & outAddr,
|
||||
const caHdrLargeArray &, const pvExistReturn &,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
|
||||
virtual caStatus createChanResponse (
|
||||
const caHdrLargeArray &, const pvAttachReturn &);
|
||||
virtual caStatus readResponse (
|
||||
casChannelI *, const caHdrLargeArray &, const smartConstGDDPointer &, const caStatus );
|
||||
virtual caStatus readNotifyResponse (
|
||||
casChannelI *, const caHdrLargeArray &, const smartConstGDDPointer &, const caStatus );
|
||||
virtual caStatus writeResponse ( const caHdrLargeArray &, const caStatus );
|
||||
virtual caStatus writeNotifyResponse ( const caHdrLargeArray &, const caStatus );
|
||||
virtual caStatus monitorResponse ( casChannelI &chan, const caHdrLargeArray &msg,
|
||||
const smartConstGDDPointer & pDesc, const caStatus status );
|
||||
virtual caStatus accessRightsResponse ( casChannelI * );
|
||||
virtual caStatus enumPostponedCreateChanResponse ( casChannelI & chan,
|
||||
const caHdrLargeArray & hdr, unsigned dbrType );
|
||||
virtual caStatus channelCreateFailedResp ( const caHdrLargeArray &,
|
||||
const caStatus createStatus );
|
||||
|
||||
virtual void eventSignal () = 0;
|
||||
|
||||
virtual ca_uint16_t protocolRevision () const = 0;
|
||||
|
||||
//
|
||||
// used only with DG clients
|
||||
//
|
||||
virtual caNetAddr fetchLastRecvAddr () const;
|
||||
virtual ca_uint32_t datagramSequenceNumber () const;
|
||||
|
||||
bool okToStartAsynchIO ();
|
||||
|
||||
casMonEvent & casMonEventFactory ( casMonitor & monitor,
|
||||
const smartConstGDDPointer & pNewValue );
|
||||
void casMonEventDestroy ( casMonEvent & );
|
||||
|
||||
casEventSys::processStatus eventSysProcess();
|
||||
|
||||
void addToEventQueue ( casEvent & );
|
||||
caStatus addToEventQueue ( casAsyncIOI &,
|
||||
bool & onTheQueue, bool & posted );
|
||||
void removeFromEventQueue ( casEvent & );
|
||||
void removeFromEventQueue ( casAsyncIOI & );
|
||||
void enableEvents ();
|
||||
void disableEvents ();
|
||||
|
||||
void setDestroyPending ();
|
||||
|
||||
casMonitor & monitorFactory (
|
||||
casChannelI & ,
|
||||
caResId clientId,
|
||||
const unsigned long count,
|
||||
const unsigned type,
|
||||
const casEventMask & );
|
||||
void destroyMonitor ( casMonitor & );
|
||||
caStatus casMonitorCallBack ( casMonitor &,
|
||||
const smartConstGDDPointer & );
|
||||
casMonitor * lookupMonitor ( const caResId &idIn );
|
||||
void postEvent ( tsDLList <casMonitor > &,
|
||||
const casEventMask &select, const gdd &event );
|
||||
void showMonitorsInList (
|
||||
const tsDLList < casMonitor > & monitorList,
|
||||
unsigned level ) const;
|
||||
|
||||
protected:
|
||||
mutable epicsMutex mutex;
|
||||
casCtx ctx;
|
||||
bool asyncIOFlag;
|
||||
|
||||
void lock ();
|
||||
void unlock ();
|
||||
|
||||
private:
|
||||
casEventSys eventSys;
|
||||
tsDLList < casAsyncIOI > ioInProgList;
|
||||
casCoreClient ( const casCoreClient & );
|
||||
casCoreClient & operator = ( const casCoreClient & );
|
||||
};
|
||||
|
||||
//
|
||||
// casClient
|
||||
//
|
||||
class casClient : public casCoreClient, public outBufClient,
|
||||
public inBufClient {
|
||||
public:
|
||||
|
||||
casClient ( caServerI &, clientBufMemoryManager &, bufSizeT ioMinSizeIn );
|
||||
virtual ~casClient ();
|
||||
|
||||
virtual void show ( unsigned level ) const;
|
||||
|
||||
caStatus sendErr ( const caHdrLargeArray *, const int reportedStatus,
|
||||
const char *pFormat, ... );
|
||||
|
||||
ca_uint16_t protocolRevision() const {return this->minor_version_number;}
|
||||
|
||||
casChannelI * lookupChannel ( const caResId &id );
|
||||
|
||||
virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0;
|
||||
|
||||
void sendVersion ();
|
||||
|
||||
protected:
|
||||
inBuf in;
|
||||
outBuf out;
|
||||
ca_uint16_t minor_version_number;
|
||||
unsigned incommingBytesToDrain;
|
||||
epicsTime lastSendTS;
|
||||
epicsTime lastRecvTS;
|
||||
|
||||
caStatus sendErrWithEpicsStatus ( const caHdrLargeArray *pMsg,
|
||||
caStatus epicsStatus, caStatus clientStatus );
|
||||
|
||||
# define logBadId(MP, DP, CACSTAT, RESID) \
|
||||
this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__, RESID)
|
||||
caStatus logBadIdWithFileAndLineno ( const caHdrLargeArray *mp,
|
||||
const void *dp, const int cacStat, const char *pFileName,
|
||||
const unsigned lineno, const unsigned resId );
|
||||
|
||||
caStatus processMsg();
|
||||
|
||||
//
|
||||
// dump message to stderr
|
||||
//
|
||||
void dumpMsg ( const caHdrLargeArray *mp, const void *dp, const char *pFormat, ... );
|
||||
|
||||
|
||||
private:
|
||||
typedef caStatus ( casClient::*pCASMsgHandler ) ();
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
virtual caStatus uknownMessageAction () = 0;
|
||||
caStatus ignoreMsgAction ();
|
||||
virtual caStatus versionAction ();
|
||||
virtual caStatus eventAddAction ();
|
||||
virtual caStatus eventCancelAction ();
|
||||
virtual caStatus readAction ();
|
||||
virtual caStatus readNotifyAction ();
|
||||
virtual caStatus writeAction ();
|
||||
virtual caStatus searchAction ();
|
||||
virtual caStatus eventsOffAction ();
|
||||
virtual caStatus eventsOnAction ();
|
||||
virtual caStatus readSyncAction ();
|
||||
virtual caStatus clearChannelAction ();
|
||||
virtual caStatus claimChannelAction ();
|
||||
virtual caStatus writeNotifyAction ();
|
||||
virtual caStatus clientNameAction ();
|
||||
virtual caStatus hostNameAction ();
|
||||
virtual caStatus echoAction ();
|
||||
|
||||
virtual void userName ( char * pBuf, unsigned bufSize ) const = 0;
|
||||
|
||||
//
|
||||
// static members
|
||||
//
|
||||
static void loadProtoJumpTable();
|
||||
static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||||
static bool msgHandlersInit;
|
||||
|
||||
casClient ( const casClient & );
|
||||
casClient & operator = ( const casClient & );
|
||||
};
|
||||
|
||||
//
|
||||
// casStrmClient
|
||||
//
|
||||
class casStrmClient :
|
||||
public casClient,
|
||||
public tsDLNode<casStrmClient> {
|
||||
public:
|
||||
casStrmClient ( caServerI &, clientBufMemoryManager & );
|
||||
virtual ~casStrmClient();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
void flush ();
|
||||
|
||||
//
|
||||
// installChannel()
|
||||
//
|
||||
void installChannel(casChannelI &chan);
|
||||
|
||||
//
|
||||
// removeChannel()
|
||||
//
|
||||
void removeChannel(casChannelI &chan);
|
||||
|
||||
//
|
||||
// one function for each CA request type that has
|
||||
// asynchronous completion
|
||||
//
|
||||
virtual caStatus createChanResponse (const caHdrLargeArray &, const pvAttachReturn &);
|
||||
caStatus readResponse (casChannelI *pChan, const caHdrLargeArray &msg,
|
||||
const smartConstGDDPointer &pDesc, const caStatus status);
|
||||
caStatus readNotifyResponse (casChannelI *pChan, const caHdrLargeArray &msg,
|
||||
const smartConstGDDPointer &pDesc, const caStatus status);
|
||||
caStatus writeResponse (const caHdrLargeArray &msg, const caStatus status);
|
||||
caStatus writeNotifyResponse (const caHdrLargeArray &msg, const caStatus status);
|
||||
caStatus monitorResponse ( casChannelI & chan, const caHdrLargeArray & msg,
|
||||
const smartConstGDDPointer & pDesc, const caStatus status );
|
||||
caStatus enumPostponedCreateChanResponse ( casChannelI & chan,
|
||||
const caHdrLargeArray & hdr, unsigned dbrType );
|
||||
caStatus channelCreateFailedResp ( const caHdrLargeArray &,
|
||||
const caStatus createStatus );
|
||||
|
||||
caStatus disconnectChan ( caResId id );
|
||||
|
||||
unsigned getDebugLevel () const;
|
||||
|
||||
virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
|
||||
private:
|
||||
tsDLList<casChannelI> chanList;
|
||||
char *pUserName;
|
||||
char *pHostName;
|
||||
|
||||
//
|
||||
// createChannel()
|
||||
//
|
||||
caStatus createChannel (const char *pName);
|
||||
|
||||
//
|
||||
// verify read/write requests
|
||||
//
|
||||
caStatus verifyRequest (casChannelI *&pChan);
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
caStatus uknownMessageAction ();
|
||||
caStatus eventAddAction ();
|
||||
caStatus eventCancelAction ();
|
||||
caStatus readAction ();
|
||||
caStatus readNotifyAction ();
|
||||
caStatus writeAction ();
|
||||
caStatus eventsOffAction ();
|
||||
caStatus eventsOnAction ();
|
||||
caStatus readSyncAction ();
|
||||
caStatus clearChannelAction ();
|
||||
caStatus claimChannelAction ();
|
||||
caStatus writeNotifyAction ();
|
||||
caStatus clientNameAction ();
|
||||
caStatus hostNameAction ();
|
||||
|
||||
//
|
||||
// accessRightsResponse()
|
||||
//
|
||||
caStatus accessRightsResponse (casChannelI *pciu);
|
||||
|
||||
//
|
||||
// these prepare the gdd based on what is in the ca hdr
|
||||
//
|
||||
caStatus read (smartGDDPointer &pDesc);
|
||||
caStatus write ();
|
||||
|
||||
caStatus writeArrayData();
|
||||
caStatus writeScalarData();
|
||||
caStatus writeString();
|
||||
|
||||
//
|
||||
// io independent send/recv
|
||||
//
|
||||
outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT & nBytesSent );
|
||||
inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv,
|
||||
inBufClient::fillParameter parm, bufSizeT & nByesRecv );
|
||||
|
||||
virtual xBlockingStatus blockingState() const = 0;
|
||||
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT &nBytesActual ) = 0;
|
||||
|
||||
caStatus readNotifyFailureResponse ( const caHdrLargeArray & msg,
|
||||
const caStatus ECA_XXXX );
|
||||
|
||||
caStatus monitorFailureResponse ( const caHdrLargeArray & msg,
|
||||
const caStatus ECA_XXXX );
|
||||
|
||||
caStatus writeNotifyResponseECA_XXX ( const caHdrLargeArray &msg,
|
||||
const caStatus status );
|
||||
|
||||
caStatus casMonitorCallBack ( casMonitor &,
|
||||
const smartConstGDDPointer & pValue );
|
||||
|
||||
casStrmClient ( const casStrmClient & );
|
||||
casStrmClient & operator = ( const casStrmClient & );
|
||||
};
|
||||
|
||||
class casDGIntfIO;
|
||||
|
||||
|
||||
//
|
||||
// casDGClient
|
||||
//
|
||||
class casDGClient : public casClient {
|
||||
public:
|
||||
casDGClient ( caServerI &serverIn, clientBufMemoryManager & );
|
||||
virtual ~casDGClient();
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
|
||||
//
|
||||
// only for use with DG io
|
||||
//
|
||||
void sendBeacon ( ca_uint32_t beaconNumber );
|
||||
|
||||
virtual void sendBeaconIO ( char &msg, bufSizeT length,
|
||||
aitUint16 &portField, aitUint32 &addrField ) = 0;
|
||||
|
||||
void destroy ();
|
||||
|
||||
unsigned getDebugLevel () const;
|
||||
|
||||
void hostName ( char * pBuf, unsigned bufSize ) const;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
|
||||
caNetAddr fetchLastRecvAddr () const;
|
||||
|
||||
virtual caNetAddr serverAddress () const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
caStatus processDG ();
|
||||
|
||||
private:
|
||||
caNetAddr lastRecvAddr;
|
||||
ca_uint32_t seqNoOfReq;
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
//
|
||||
caStatus searchAction ();
|
||||
caStatus uknownMessageAction ();
|
||||
|
||||
//
|
||||
// searchFailResponse()
|
||||
//
|
||||
caStatus searchFailResponse ( const caHdrLargeArray *pMsg );
|
||||
|
||||
caStatus searchResponse ( const caHdrLargeArray &,
|
||||
const pvExistReturn & retVal );
|
||||
|
||||
caStatus asyncSearchResponse ( const caNetAddr & outAddr,
|
||||
const caHdrLargeArray & msg, const pvExistReturn & retVal,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
|
||||
|
||||
//
|
||||
// IO depen
|
||||
//
|
||||
outBufClient::flushCondition xSend ( char *pBufIn, bufSizeT nBytesAvailableToSend,
|
||||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent );
|
||||
inBufClient::fillCondition xRecv ( char *pBufIn, bufSizeT nBytesToRecv,
|
||||
fillParameter parm, bufSizeT &nByesRecv );
|
||||
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
const caNetAddr & addr ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
fillParameter parm, bufSizeT &nBytesActual, caNetAddr & addr ) = 0;
|
||||
|
||||
caStatus versionAction ();
|
||||
|
||||
ca_uint32_t datagramSequenceNumber () const;
|
||||
|
||||
//
|
||||
// cadg
|
||||
//
|
||||
struct cadg {
|
||||
caNetAddr cadg_addr; // invalid address indicates pad
|
||||
bufSizeT cadg_nBytes;
|
||||
};
|
||||
|
||||
casDGClient ( const casDGClient & );
|
||||
casDGClient & operator = ( const casDGClient & );
|
||||
};
|
||||
|
||||
//
|
||||
// casEventMaskEntry
|
||||
//
|
||||
class casEventMaskEntry : public tsSLNode<casEventMaskEntry>,
|
||||
public casEventMask, public stringId {
|
||||
public:
|
||||
casEventMaskEntry (casEventRegistry ®In,
|
||||
casEventMask maskIn, const char *pName);
|
||||
virtual ~casEventMaskEntry();
|
||||
void show (unsigned level) const;
|
||||
|
||||
virtual void destroy();
|
||||
private:
|
||||
casEventRegistry ®
|
||||
casEventMaskEntry ( const casEventMaskEntry & );
|
||||
casEventMaskEntry & operator = ( const casEventMaskEntry & );
|
||||
};
|
||||
|
||||
//
|
||||
// casEventRegistry
|
||||
//
|
||||
class casEventRegistry : private resTable <casEventMaskEntry, stringId> {
|
||||
friend class casEventMaskEntry;
|
||||
public:
|
||||
|
||||
casEventRegistry () : maskBitAllocator(0) {}
|
||||
|
||||
virtual ~casEventRegistry();
|
||||
|
||||
casEventMask registerEvent (const char *pName);
|
||||
|
||||
void show (unsigned level) const;
|
||||
|
||||
private:
|
||||
unsigned maskBitAllocator;
|
||||
|
||||
casEventMask maskAllocator();
|
||||
casEventRegistry ( const casEventRegistry & );
|
||||
casEventRegistry & operator = ( const casEventRegistry & );
|
||||
};
|
||||
|
||||
#include "casIOD.h" // IO dependent
|
||||
#include "casOSD.h" // OS dependent
|
||||
|
||||
class beaconTimer;
|
||||
class beaconAnomalyGovernor;
|
||||
|
||||
//
|
||||
// caServerI
|
||||
//
|
||||
class caServerI :
|
||||
public caServerOS,
|
||||
public caServerIO,
|
||||
public ioBlockedList,
|
||||
private chronIntIdResTable<casRes>,
|
||||
public casEventRegistry {
|
||||
public:
|
||||
caServerI ( caServer &tool );
|
||||
~caServerI ();
|
||||
|
||||
void installClient (casStrmClient *pClient);
|
||||
void removeClient (casStrmClient *pClient);
|
||||
|
||||
bool roomForNewChannel() const;
|
||||
|
||||
unsigned getDebugLevel() const { return debugLevel; }
|
||||
inline void setDebugLevel ( unsigned debugLevelIn );
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
casMonitor * lookupMonitor ( const caResId &idIn );
|
||||
casChannelI * lookupChannel ( const caResId &idIn );
|
||||
|
||||
caServer *getAdapter ();
|
||||
|
||||
void installItem ( casRes & res );
|
||||
casRes * removeItem ( casRes & res );
|
||||
|
||||
caServer * operator -> ();
|
||||
|
||||
void connectCB (casIntfOS &);
|
||||
|
||||
casEventMask valueEventMask() const; // DBE_VALUE registerEvent("value")
|
||||
casEventMask logEventMask() const; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEventMask() const; // DBE_ALARM registerEvent("alarm")
|
||||
|
||||
unsigned subscriptionEventsProcessed () const;
|
||||
void incrEventsProcessedCounter ();
|
||||
|
||||
unsigned subscriptionEventsPosted () const;
|
||||
void incrEventsPostedCounter ();
|
||||
|
||||
void lock () const;
|
||||
void unlock () const;
|
||||
|
||||
void generateBeaconAnomaly ();
|
||||
|
||||
casMonEvent & casMonEventFactory ( casMonitor & monitor,
|
||||
const smartConstGDDPointer & pNewValue );
|
||||
void casMonEventDestroy ( casMonEvent & );
|
||||
|
||||
casMonitor & casMonitorFactory ( casChannelI &,
|
||||
caResId clientId, const unsigned long count,
|
||||
const unsigned type, const casEventMask &,
|
||||
casMonitorCallbackInterface & );
|
||||
void casMonitorDestroy ( casMonitor & );
|
||||
|
||||
private:
|
||||
clientBufMemoryManager clientBufMemMgr;
|
||||
mutable epicsMutex mutex;
|
||||
tsDLList < casStrmClient > clientList;
|
||||
tsDLList < casIntfOS > intfList;
|
||||
tsFreeList < casMonEvent, 1024 > casMonEventFreeList;
|
||||
tsFreeList < casMonitor, 1024 > casMonitorFreeList;
|
||||
caServer & adapter;
|
||||
beaconTimer & beaconTmr;
|
||||
beaconAnomalyGovernor & beaconAnomalyGov;
|
||||
unsigned debugLevel;
|
||||
unsigned nEventsProcessed;
|
||||
unsigned nEventsPosted;
|
||||
|
||||
casEventMask valueEvent; // DBE_VALUE registerEvent("value")
|
||||
casEventMask logEvent; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm")
|
||||
|
||||
caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr,
|
||||
bool addConfigAddr);
|
||||
|
||||
void sendBeacon ( ca_uint32_t beaconNo );
|
||||
|
||||
caServerI ( const caServerI & );
|
||||
caServerI & operator = ( const caServerI & );
|
||||
|
||||
friend class beaconAnomalyGovernor;
|
||||
friend class beaconTimer;
|
||||
};
|
||||
|
||||
#define CAServerConnectPendQueueSize 10
|
||||
|
||||
/*
|
||||
* If there is insufficent space to allocate an
|
||||
* asynch IO in progress block then we will end up
|
||||
* with pIoInProgress nill and activeAsyncIO true.
|
||||
* This protects the app from simultaneous multiple
|
||||
* invocation of async IO on the same PV.
|
||||
*/
|
||||
#define maxIOInProg 50
|
||||
|
||||
bool convertContainerMemberToAtomic ( gdd & dd,
|
||||
aitUint32 appType, aitUint32 elemCount );
|
||||
|
||||
#endif /*INCLserverh*/
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* caServerOS.c
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// CA server
|
||||
//
|
||||
#include "server.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
//
|
||||
// caServerOS::caServerOS()
|
||||
//
|
||||
caServerOS::caServerOS ()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// caServerOS::~caServerOS()
|
||||
//
|
||||
caServerOS::~caServerOS()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,29 +8,23 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
//
|
||||
// casDGIntfOS.cc
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// CA server
|
||||
//
|
||||
#include "server.h"
|
||||
#include "inBufIL.h" // inBuf in line func
|
||||
#include "outBufIL.h" // outBuf in line func
|
||||
#include "casIODIL.h" // IO Depen in line func
|
||||
#include "casCoreClientIL.h"
|
||||
|
||||
#include "fdManager.h"
|
||||
|
||||
#define epicsExportSharedFunc
|
||||
#include "casDGIntfOS.h"
|
||||
|
||||
//
|
||||
// casDGReadReg
|
||||
//
|
||||
class casDGReadReg : public fdReg {
|
||||
public:
|
||||
casDGReadReg (casDGIntfOS &osIn) :
|
||||
casDGReadReg ( casDGIntfOS & osIn ) :
|
||||
fdReg (osIn.getFD(), fdrRead), os (osIn) {}
|
||||
~casDGReadReg ();
|
||||
|
||||
|
||||
@@ -16,15 +16,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fdManager.h"
|
||||
|
||||
//
|
||||
// CA server
|
||||
//
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casIntfOS.h"
|
||||
|
||||
//
|
||||
// casServerReg
|
||||
//
|
||||
class casServerReg : public fdReg {
|
||||
public:
|
||||
casServerReg (casIntfOS &osIn) :
|
||||
@@ -37,9 +33,6 @@ private:
|
||||
casServerReg & operator = ( const casServerReg & );
|
||||
};
|
||||
|
||||
//
|
||||
// casIntfOS::casIntfOS()
|
||||
//
|
||||
casIntfOS::casIntfOS ( caServerI & casIn, clientBufMemoryManager & memMgrIn,
|
||||
const caNetAddr & addrIn, bool autoBeaconAddr, bool addConfigBeaconAddr ) :
|
||||
casIntfIO ( addrIn ),
|
||||
@@ -52,9 +45,6 @@ casIntfOS::casIntfOS ( caServerI & casIn, clientBufMemoryManager & memMgrIn,
|
||||
this->pRdReg = new casServerReg(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// casIntfOS::~casIntfOS()
|
||||
//
|
||||
casIntfOS::~casIntfOS()
|
||||
{
|
||||
if (this->pRdReg) {
|
||||
@@ -62,25 +52,16 @@ casIntfOS::~casIntfOS()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casServerReg::callBack()
|
||||
//
|
||||
void casServerReg::callBack()
|
||||
{
|
||||
assert(this->os.pRdReg);
|
||||
this->os.cas.connectCB(this->os);
|
||||
}
|
||||
|
||||
//
|
||||
// casServerReg::~casServerReg()
|
||||
//
|
||||
casServerReg::~casServerReg()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casIntfOS::show ()
|
||||
//
|
||||
void casIntfOS::show ( unsigned level ) const
|
||||
{
|
||||
printf ( "casIntfOS at %p\n",
|
||||
@@ -88,9 +69,6 @@ void casIntfOS::show ( unsigned level ) const
|
||||
this->casDGIntfOS::show ( level );
|
||||
}
|
||||
|
||||
//
|
||||
// casIntfOS::serverAddress ()
|
||||
//
|
||||
caNetAddr casIntfOS::serverAddress () const
|
||||
{
|
||||
return this->casIntfIO::serverAddress();
|
||||
|
||||
@@ -29,208 +29,23 @@
|
||||
#endif
|
||||
|
||||
class caServerI;
|
||||
class caServerOS;
|
||||
|
||||
class casServerReg;
|
||||
|
||||
//
|
||||
// caServerOS
|
||||
//
|
||||
class caServerOS {
|
||||
public:
|
||||
caServerOS ();
|
||||
virtual ~caServerOS ();
|
||||
private:
|
||||
friend class casServerReg;
|
||||
};
|
||||
|
||||
class casDGReadReg;
|
||||
class casDGBCastReadReg;
|
||||
class casDGWriteReg;
|
||||
|
||||
//
|
||||
// class casDGEvWakeup
|
||||
//
|
||||
class casDGEvWakeup : public epicsTimerNotify {
|
||||
public:
|
||||
casDGEvWakeup ();
|
||||
virtual ~casDGEvWakeup();
|
||||
void show ( unsigned level ) const;
|
||||
void start ( class casDGIntfOS &osIn );
|
||||
private:
|
||||
epicsTimer &timer;
|
||||
class casDGIntfOS *pOS;
|
||||
expireStatus expire( const epicsTime & currentTime );
|
||||
casDGEvWakeup ( const casDGEvWakeup & );
|
||||
casDGEvWakeup & operator = ( const casDGEvWakeup & );
|
||||
};
|
||||
|
||||
//
|
||||
// class casDGIOWakeup
|
||||
//
|
||||
class casDGIOWakeup : public epicsTimerNotify {
|
||||
public:
|
||||
casDGIOWakeup ();
|
||||
virtual ~casDGIOWakeup ();
|
||||
void show ( unsigned level ) const;
|
||||
void start ( class casDGIntfOS &osIn );
|
||||
private:
|
||||
epicsTimer &timer;
|
||||
class casDGIntfOS *pOS;
|
||||
expireStatus expire( const epicsTime & currentTime );
|
||||
casDGIOWakeup ( const casDGIOWakeup & );
|
||||
casDGIOWakeup & operator = ( const casDGIOWakeup & );
|
||||
};
|
||||
|
||||
//
|
||||
// casDGIntfOS
|
||||
//
|
||||
class casDGIntfOS : public casDGIntfIO {
|
||||
friend class casDGReadReg;
|
||||
friend class casDGBCastReadReg;
|
||||
friend class casDGWriteReg;
|
||||
public:
|
||||
casDGIntfOS ( caServerI &, clientBufMemoryManager &,
|
||||
const caNetAddr & addr, bool autoBeaconAddr = true,
|
||||
bool addConfigBeaconAddr = false);
|
||||
|
||||
virtual ~casDGIntfOS ();
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
|
||||
void processInput();
|
||||
|
||||
void eventFlush ();
|
||||
|
||||
private:
|
||||
casDGIOWakeup ioWk;
|
||||
casDGEvWakeup evWk;
|
||||
casDGReadReg *pRdReg;
|
||||
casDGBCastReadReg *pBCastRdReg; // fix for solaris bug
|
||||
casDGWriteReg *pWtReg;
|
||||
bool sendBlocked;
|
||||
|
||||
void armRecv ();
|
||||
void armSend ();
|
||||
|
||||
void disarmRecv ();
|
||||
void disarmSend ();
|
||||
|
||||
void recvCB ( inBufClient::fillParameter parm );
|
||||
void sendCB ();
|
||||
|
||||
void sendBlockSignal ();
|
||||
|
||||
void ioBlockedSignal ();
|
||||
|
||||
void eventSignal ();
|
||||
|
||||
casDGIntfOS ( const casDGIntfOS & );
|
||||
casDGIntfOS & operator = ( const casDGIntfOS & );
|
||||
};
|
||||
|
||||
//
|
||||
// casIntfOS
|
||||
//
|
||||
class casIntfOS : public casIntfIO, public tsDLNode<casIntfOS>,
|
||||
public casDGIntfOS
|
||||
{
|
||||
friend class casServerReg;
|
||||
public:
|
||||
casIntfOS ( caServerI &, clientBufMemoryManager &, const caNetAddr &,
|
||||
bool autoBeaconAddr = true, bool addConfigBeaconAddr = false );
|
||||
virtual ~casIntfOS();
|
||||
void show ( unsigned level ) const;
|
||||
caNetAddr serverAddress () const;
|
||||
private:
|
||||
caServerI & cas;
|
||||
casServerReg * pRdReg;
|
||||
|
||||
casIntfOS ( const casIntfOS & );
|
||||
casIntfOS & operator = ( const casIntfOS & );
|
||||
};
|
||||
|
||||
class casStreamWriteReg;
|
||||
class casStreamReadReg;
|
||||
|
||||
//
|
||||
// class casStreamIOWakeup
|
||||
//
|
||||
class casStreamIOWakeup : public epicsTimerNotify {
|
||||
public:
|
||||
casStreamIOWakeup ();
|
||||
virtual ~casStreamIOWakeup ();
|
||||
void show ( unsigned level ) const;
|
||||
void start ( casStreamOS &osIn );
|
||||
private:
|
||||
epicsTimer &timer;
|
||||
casStreamOS *pOS;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
casStreamIOWakeup ( const casStreamIOWakeup & );
|
||||
casStreamIOWakeup & operator = ( const casStreamIOWakeup & );
|
||||
};
|
||||
|
||||
//
|
||||
// class casStreamEvWakeup
|
||||
//
|
||||
class casStreamEvWakeup : public epicsTimerNotify {
|
||||
public:
|
||||
casStreamEvWakeup ();
|
||||
virtual ~casStreamEvWakeup ();
|
||||
void show ( unsigned level ) const;
|
||||
void start ( casStreamOS &osIn );
|
||||
private:
|
||||
epicsTimer &timer;
|
||||
casStreamOS *pOS;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
casStreamEvWakeup ( const casStreamEvWakeup & );
|
||||
casStreamEvWakeup & operator = ( const casStreamEvWakeup & );
|
||||
};
|
||||
|
||||
//
|
||||
// casStreamOS
|
||||
//
|
||||
class casStreamOS : public casStreamIO {
|
||||
public:
|
||||
casStreamOS ( caServerI &, clientBufMemoryManager &,
|
||||
const ioArgsToNewStreamIO & );
|
||||
~casStreamOS ();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
casProcCond processInput ();
|
||||
|
||||
void eventFlush ();
|
||||
|
||||
private:
|
||||
casStreamEvWakeup evWk;
|
||||
casStreamIOWakeup ioWk;
|
||||
casStreamWriteReg * pWtReg;
|
||||
casStreamReadReg * pRdReg;
|
||||
bool sendBlocked;
|
||||
//
|
||||
//
|
||||
//
|
||||
inline void armSend ();
|
||||
inline void armRecv ();
|
||||
inline void disarmSend();
|
||||
inline void disarmRecv();
|
||||
|
||||
void recvCB ();
|
||||
void sendCB ();
|
||||
|
||||
void sendBlockSignal ();
|
||||
|
||||
void ioBlockedSignal ();
|
||||
|
||||
void eventSignal ();
|
||||
|
||||
casStreamOS ( const casStreamOS & );
|
||||
casStreamOS & operator = ( const casStreamOS & );
|
||||
|
||||
friend class casStreamWriteReg;
|
||||
friend class casStreamReadReg;
|
||||
};
|
||||
|
||||
// no additions below this line
|
||||
#endif // includeCASOSDH
|
||||
|
||||
@@ -18,13 +18,10 @@
|
||||
// there isnt enough memory
|
||||
//
|
||||
|
||||
//
|
||||
// CA server
|
||||
//
|
||||
#include "server.h"
|
||||
#include "inBufIL.h" // inBuf inline func
|
||||
#include "outBufIL.h" // outBuf inline func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
#include "fdManager.h"
|
||||
|
||||
#define epicsExportSharedFunc
|
||||
#include "casStreamOS.h"
|
||||
|
||||
//
|
||||
// casStreamReadReg
|
||||
@@ -262,7 +259,7 @@ inline void casStreamOS::armRecv()
|
||||
//
|
||||
inline void casStreamOS::disarmRecv()
|
||||
{
|
||||
if (this->pRdReg) {
|
||||
if ( this->pRdReg ) {
|
||||
delete this->pRdReg;
|
||||
}
|
||||
}
|
||||
@@ -286,7 +283,7 @@ inline void casStreamOS::armSend()
|
||||
//
|
||||
inline void casStreamOS::disarmSend ()
|
||||
{
|
||||
if (this->pWtReg) {
|
||||
if ( this->pWtReg ) {
|
||||
delete this->pWtReg;
|
||||
}
|
||||
}
|
||||
@@ -329,8 +326,8 @@ casStreamOS::casStreamOS ( caServerI & cas, clientBufMemoryManager & bufMgrIn,
|
||||
casStreamIO ( cas, bufMgrIn, ioArgs ),
|
||||
pWtReg ( 0 ), pRdReg ( 0 ), sendBlocked ( false )
|
||||
{
|
||||
this->xSetNonBlocking();
|
||||
this->armRecv();
|
||||
this->xSetNonBlocking ();
|
||||
this->armRecv ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -341,16 +338,16 @@ casStreamOS::~casStreamOS()
|
||||
//
|
||||
// attempt to flush out any remaining messages
|
||||
//
|
||||
this->flush();
|
||||
this->flush ();
|
||||
|
||||
this->disarmSend();
|
||||
this->disarmRecv();
|
||||
this->disarmSend ();
|
||||
this->disarmRecv ();
|
||||
}
|
||||
|
||||
//
|
||||
// casStreamOS::show()
|
||||
//
|
||||
void casStreamOS::show(unsigned level) const
|
||||
void casStreamOS::show ( unsigned level ) const
|
||||
{
|
||||
this->casStrmClient::show(level);
|
||||
printf("casStreamOS at %p\n",
|
||||
@@ -371,7 +368,7 @@ void casStreamOS::show(unsigned level) const
|
||||
//
|
||||
void casStreamReadReg::show(unsigned level) const
|
||||
{
|
||||
this->fdReg::show(level);
|
||||
this->fdReg::show ( level );
|
||||
printf ( "casStreamReadReg at %p\n",
|
||||
static_cast <const void *> ( this ) );
|
||||
}
|
||||
@@ -381,7 +378,7 @@ void casStreamReadReg::show(unsigned level) const
|
||||
//
|
||||
void casStreamReadReg::callBack ()
|
||||
{
|
||||
this->os.recvCB();
|
||||
this->os.recvCB ();
|
||||
//
|
||||
// NO CODE HERE
|
||||
// (casStreamOS::recvCB() may up indirectly deleting this object)
|
||||
@@ -391,7 +388,7 @@ void casStreamReadReg::callBack ()
|
||||
//
|
||||
// casStreamOS::recvCB()
|
||||
//
|
||||
void casStreamOS::recvCB()
|
||||
void casStreamOS::recvCB ()
|
||||
{
|
||||
assert ( this->pRdReg );
|
||||
|
||||
@@ -400,12 +397,12 @@ void casStreamOS::recvCB()
|
||||
//
|
||||
inBufClient::fillCondition fillCond = this->in.fill();
|
||||
if ( fillCond == casFillDisconnect ) {
|
||||
delete this;
|
||||
this->getCAS().destroyClient ( *this );
|
||||
}
|
||||
else {
|
||||
casProcCond procCond = this->processInput();
|
||||
if (procCond == casProcDisconnect) {
|
||||
delete this;
|
||||
this->getCAS().destroyClient ( *this );
|
||||
}
|
||||
else if ( this->in.full() ) {
|
||||
//
|
||||
@@ -482,7 +479,7 @@ void casStreamOS::sendCB()
|
||||
// called from a client member function
|
||||
// higher up on the stack
|
||||
//
|
||||
delete this;
|
||||
this->getCAS().destroyClient ( *this );
|
||||
//
|
||||
// must _not_ touch "this" pointer
|
||||
// after the destroy
|
||||
@@ -507,7 +504,7 @@ void casStreamOS::sendCB()
|
||||
// called from a client member function
|
||||
// higher up on the stack
|
||||
//
|
||||
delete this;
|
||||
this->getCAS().destroyClient ( *this );
|
||||
//
|
||||
// must _not_ touch "this" pointer
|
||||
// after the destroy
|
||||
@@ -527,9 +524,9 @@ void casStreamOS::sendCB()
|
||||
// to process the input queue in case we were send
|
||||
// blocked.
|
||||
//
|
||||
casProcCond procCond = this->processInput();
|
||||
if (procCond == casProcDisconnect) {
|
||||
delete this;
|
||||
casProcCond procCond = this->processInput ();
|
||||
if ( procCond == casProcDisconnect ) {
|
||||
this->getCAS().destroyClient ( *this );
|
||||
}
|
||||
else {
|
||||
//
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "server.h"
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "epicsAssert.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "ioBlocked.h"
|
||||
|
||||
//
|
||||
// ioBlocked::ioBlocked ()
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include "epicsSignal.h"
|
||||
#include "envDefs.h"
|
||||
#include "caProto.h"
|
||||
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caServerIO.h"
|
||||
|
||||
static char *getToken (const char **ppString, char *pBuf, unsigned bufSIze);
|
||||
static char * getToken ( const char **ppString, char *pBuf, unsigned bufSIze );
|
||||
|
||||
int caServerIO::staticInitialized;
|
||||
|
||||
@@ -33,7 +36,7 @@ caServerIO::caServerIO ()
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
caServerIO::staticInit();
|
||||
caServerIO::staticInit ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -55,22 +58,22 @@ void caServerIO::locateInterfaces ()
|
||||
// clients to find the server). If this also isnt available
|
||||
// then use a hard coded default - CA_SERVER_PORT.
|
||||
//
|
||||
if (envGetConfigParamPtr(&EPICS_CAS_SERVER_PORT)) {
|
||||
if ( envGetConfigParamPtr ( & EPICS_CAS_SERVER_PORT ) ) {
|
||||
port = envGetInetPortConfigParam (
|
||||
&EPICS_CAS_SERVER_PORT,
|
||||
static_cast <unsigned short> (CA_SERVER_PORT));
|
||||
static_cast <unsigned short> ( CA_SERVER_PORT ) );
|
||||
}
|
||||
else {
|
||||
port = envGetInetPortConfigParam (
|
||||
&EPICS_CA_SERVER_PORT,
|
||||
static_cast <unsigned short> (CA_SERVER_PORT));
|
||||
& EPICS_CA_SERVER_PORT,
|
||||
static_cast <unsigned short> ( CA_SERVER_PORT ) );
|
||||
}
|
||||
|
||||
memset ((char *)&saddr,0,sizeof(saddr));
|
||||
|
||||
pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf);
|
||||
pStr = envGetConfigParam ( &EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf );
|
||||
if ( ! pStr ) {
|
||||
pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf);
|
||||
pStr = envGetConfigParam ( &EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf );
|
||||
}
|
||||
if (pStr) {
|
||||
if (strstr(pStr,"no")||strstr(pStr,"NO")) {
|
||||
@@ -93,11 +96,11 @@ void caServerIO::locateInterfaces ()
|
||||
// bind to the the interfaces specified - otherwise wildcard
|
||||
// with INADDR_ANY and allow clients to attach from any interface
|
||||
//
|
||||
pStr = envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST);
|
||||
pStr = envGetConfigParamPtr ( & EPICS_CAS_INTF_ADDR_LIST );
|
||||
if (pStr) {
|
||||
bool configAddrOnceFlag = true;
|
||||
stat = S_cas_noInterface;
|
||||
while ( (pToken = getToken(&pStr, buf, sizeof(buf))) ) {
|
||||
while ( (pToken = getToken ( & pStr, buf, sizeof ( buf ) ) ) ) {
|
||||
int status;
|
||||
|
||||
status = aToIPAddr (pToken, port, &saddr);
|
||||
|
||||
@@ -13,19 +13,16 @@
|
||||
* (505) 665 1831
|
||||
*/
|
||||
|
||||
//
|
||||
//
|
||||
// Should I fetch the MTU from the outgoing interface?
|
||||
//
|
||||
//
|
||||
|
||||
#include "server.h"
|
||||
#include "addrList.h"
|
||||
#include "casIODIL.h"
|
||||
|
||||
/*
|
||||
* forcePort ()
|
||||
*/
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casDGIntfIO.h"
|
||||
#include "ipIgnoreEntry.h"
|
||||
|
||||
static void forcePort (ELLLIST *pList, unsigned short port)
|
||||
{
|
||||
osiSockAddrNode *pNode;
|
||||
@@ -40,9 +37,6 @@ static void forcePort (ELLLIST *pList, unsigned short port)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// casDGIntfIO::casDGIntfIO()
|
||||
//
|
||||
casDGIntfIO::casDGIntfIO ( caServerI & serverIn, clientBufMemoryManager & memMgr,
|
||||
const caNetAddr & addr, bool autoBeaconAddr, bool addConfigBeaconAddr ) :
|
||||
casDGClient ( serverIn, memMgr )
|
||||
@@ -276,9 +270,6 @@ casDGIntfIO::~casDGIntfIO()
|
||||
osiSockRelease ();
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::show()
|
||||
//
|
||||
void casDGIntfIO::show (unsigned level) const
|
||||
{
|
||||
printf ( "casDGIntfIO at %p\n",
|
||||
@@ -287,9 +278,6 @@ void casDGIntfIO::show (unsigned level) const
|
||||
this->casDGClient::show (level);
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::xSetNonBlocking()
|
||||
//
|
||||
void casDGIntfIO::xSetNonBlocking()
|
||||
{
|
||||
int status;
|
||||
@@ -302,9 +290,6 @@ void casDGIntfIO::xSetNonBlocking()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::osdRecv()
|
||||
//
|
||||
inBufClient::fillCondition
|
||||
casDGIntfIO::osdRecv ( char * pBufIn, bufSizeT size, // X aCC 361
|
||||
fillParameter parm, bufSizeT & actualSize, caNetAddr & fromOut )
|
||||
@@ -352,9 +337,6 @@ casDGIntfIO::osdRecv ( char * pBufIn, bufSizeT size, // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::osdSend()
|
||||
//
|
||||
outBufClient::flushCondition
|
||||
casDGIntfIO::osdSend ( const char * pBufIn, bufSizeT size, // X aCC 361
|
||||
const caNetAddr & to )
|
||||
@@ -384,9 +366,6 @@ casDGIntfIO::osdSend ( const char * pBufIn, bufSizeT size, // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::incomingBytesPresent()
|
||||
//
|
||||
bufSizeT casDGIntfIO::incomingBytesPresent () const // X aCC 361
|
||||
{
|
||||
int status;
|
||||
@@ -407,9 +386,6 @@ bufSizeT casDGIntfIO::incomingBytesPresent () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::sendBeaconIO()
|
||||
//
|
||||
void casDGIntfIO::sendBeaconIO ( char & msg, unsigned length,
|
||||
aitUint16 & portField, aitUint32 & addrField )
|
||||
{
|
||||
@@ -455,9 +431,6 @@ void casDGIntfIO::sendBeaconIO ( char & msg, unsigned length,
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::optimumInBufferSize()
|
||||
//
|
||||
bufSizeT casDGIntfIO::optimumInBufferSize ()
|
||||
{
|
||||
|
||||
@@ -491,9 +464,6 @@ bufSizeT casDGIntfIO::optimumInBufferSize ()
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::optimumOutBufferSize()
|
||||
//
|
||||
bufSizeT casDGIntfIO::optimumOutBufferSize ()
|
||||
{
|
||||
|
||||
@@ -528,10 +498,6 @@ bufSizeT casDGIntfIO::optimumOutBufferSize ()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// casDGIntfIO::makeSockDG ()
|
||||
//
|
||||
SOCKET casDGIntfIO::makeSockDG ()
|
||||
{
|
||||
int yes = true;
|
||||
@@ -611,10 +577,6 @@ SOCKET casDGIntfIO::makeSockDG ()
|
||||
return newSock;
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::getFD()
|
||||
// (avoid problems with the GNU inliner)
|
||||
//
|
||||
int casDGIntfIO::getFD() const
|
||||
{
|
||||
return this->sock;
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// casIOD.h - Channel Access Server BSD socket dependent wrapper
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef includeCASIODH
|
||||
#define includeCASIODH
|
||||
@@ -35,178 +31,9 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
void hostNameFromIPAddr ( const class caNetAddr * pAddr,
|
||||
char * pBuf, unsigned bufSize );
|
||||
|
||||
class ipIgnoreEntry : public tsSLNode < ipIgnoreEntry > {
|
||||
public:
|
||||
ipIgnoreEntry ( unsigned ipAddr );
|
||||
void show ( unsigned level ) const;
|
||||
bool operator == ( const ipIgnoreEntry & ) const;
|
||||
resTableIndex hash () const;
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < class ipIgnoreEntry, 128 > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < class ipIgnoreEntry, 128 > & ))
|
||||
private:
|
||||
unsigned ipAddr;
|
||||
ipIgnoreEntry ( const ipIgnoreEntry & );
|
||||
ipIgnoreEntry & operator = ( const ipIgnoreEntry & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
//
|
||||
// casDGIntfIO
|
||||
//
|
||||
class casDGIntfIO : public casDGClient {
|
||||
public:
|
||||
casDGIntfIO ( caServerI & serverIn, clientBufMemoryManager &,
|
||||
const caNetAddr & addr, bool autoBeaconAddr = true,
|
||||
bool addConfigBeaconAddr = false );
|
||||
virtual ~casDGIntfIO();
|
||||
|
||||
int getFD () const;
|
||||
int getBCastFD () const;
|
||||
bool validBCastFD () const;
|
||||
|
||||
void xSetNonBlocking ();
|
||||
void sendBeaconIO ( char & msg, bufSizeT length,
|
||||
aitUint16 &portField, aitUint32 & addrField );
|
||||
casIOState state () const;
|
||||
|
||||
outBufClient::flushCondition osdSend ( const char * pBuf, bufSizeT nBytesReq,
|
||||
const caNetAddr & addr);
|
||||
inBufClient::fillCondition osdRecv ( char * pBuf, bufSizeT nBytesReq,
|
||||
inBufClient::fillParameter parm, bufSizeT & nBytesActual, caNetAddr & addr );
|
||||
virtual void show ( unsigned level ) const;
|
||||
|
||||
static bufSizeT optimumOutBufferSize ();
|
||||
static bufSizeT optimumInBufferSize ();
|
||||
|
||||
bufSizeT incomingBytesPresent () const;
|
||||
|
||||
private:
|
||||
tsFreeList < class ipIgnoreEntry, 128 > ipIgnoreEntryFreeList;
|
||||
resTable < ipIgnoreEntry, ipIgnoreEntry > ignoreTable;
|
||||
ELLLIST beaconAddrList;
|
||||
SOCKET sock;
|
||||
SOCKET bcastRecvSock; // fix for solaris bug
|
||||
SOCKET beaconSock; // allow connect
|
||||
unsigned short dgPort;
|
||||
|
||||
static SOCKET makeSockDG ();
|
||||
casDGIntfIO ( const casDGIntfIO & );
|
||||
casDGIntfIO & operator = ( const casDGIntfIO & );
|
||||
};
|
||||
|
||||
struct ioArgsToNewStreamIO {
|
||||
caNetAddr addr;
|
||||
SOCKET sock;
|
||||
};
|
||||
|
||||
//
|
||||
// casStreamIO
|
||||
//
|
||||
class casStreamIO : public casStrmClient {
|
||||
public:
|
||||
casStreamIO ( caServerI &, clientBufMemoryManager &,
|
||||
const ioArgsToNewStreamIO & );
|
||||
~casStreamIO ();
|
||||
|
||||
int getFD () const;
|
||||
void xSetNonBlocking ();
|
||||
|
||||
casIOState state () const;
|
||||
void hostName ( char *pBuf, unsigned bufSize ) const;
|
||||
|
||||
outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
|
||||
xBlockingStatus blockingState() const;
|
||||
|
||||
bufSizeT incomingBytesPresent() const;
|
||||
|
||||
static bufSizeT optimumBufferSize ();
|
||||
|
||||
void osdShow ( unsigned level ) const;
|
||||
|
||||
const caNetAddr getAddr() const
|
||||
{
|
||||
return caNetAddr ( this->addr );
|
||||
}
|
||||
|
||||
private:
|
||||
SOCKET sock;
|
||||
struct sockaddr_in addr;
|
||||
xBlockingStatus blockingFlag;
|
||||
casStreamIO ( const casStreamIO & );
|
||||
casStreamIO & operator = ( const casStreamIO & );
|
||||
};
|
||||
|
||||
class caServerIO;
|
||||
class casDGClient;
|
||||
|
||||
class casStreamOS;
|
||||
|
||||
//
|
||||
// casIntfIO
|
||||
//
|
||||
class casIntfIO {
|
||||
public:
|
||||
casIntfIO (const caNetAddr &addr);
|
||||
virtual ~casIntfIO();
|
||||
void show(unsigned level) const;
|
||||
|
||||
int getFD() const;
|
||||
|
||||
void setNonBlocking();
|
||||
|
||||
//
|
||||
// called when we expect that a virtual circuit for a
|
||||
// client can be created
|
||||
//
|
||||
casStreamOS * newStreamClient ( caServerI & cas,
|
||||
clientBufMemoryManager & ) const;
|
||||
|
||||
caNetAddr serverAddress () const;
|
||||
|
||||
private:
|
||||
SOCKET sock;
|
||||
struct sockaddr_in addr;
|
||||
};
|
||||
|
||||
//
|
||||
// caServerIO
|
||||
//
|
||||
class caServerIO {
|
||||
public:
|
||||
caServerIO ();
|
||||
virtual ~caServerIO();
|
||||
|
||||
//
|
||||
// show status of IO subsystem
|
||||
//
|
||||
void show (unsigned level) const;
|
||||
|
||||
void locateInterfaces ();
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// static member data
|
||||
//
|
||||
static int staticInitialized;
|
||||
//
|
||||
// static member func
|
||||
//
|
||||
static inline void staticInit();
|
||||
|
||||
virtual caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr,
|
||||
bool addConfigAddr) = 0;
|
||||
};
|
||||
|
||||
// no additions below this line
|
||||
#endif // includeCASIODH
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef casIODILh
|
||||
#define casIODILh
|
||||
|
||||
//
|
||||
// casDGIntfIO::getBCastFD()
|
||||
//
|
||||
inline int casDGIntfIO::getBCastFD() const
|
||||
{
|
||||
return this->bcastRecvSock;
|
||||
}
|
||||
|
||||
//
|
||||
// casDGIntfIO::getBCastFD()
|
||||
//
|
||||
inline bool casDGIntfIO::validBCastFD() const
|
||||
{
|
||||
return this->bcastRecvSock != INVALID_SOCKET;
|
||||
}
|
||||
|
||||
#endif // casIODILh
|
||||
|
||||
@@ -13,9 +13,18 @@
|
||||
// Author Jeff Hill
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "server.h"
|
||||
#include "errlog.h"
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "epicsAssert.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casdef.h"
|
||||
#include "caNetAddr.h"
|
||||
#include "casIntfIO.h"
|
||||
#include "casStreamIO.h"
|
||||
#include "casStreamOS.h"
|
||||
|
||||
//
|
||||
// 5 appears to be a TCP/IP built in maximum
|
||||
@@ -25,9 +34,9 @@ const unsigned caServerConnectPendQueueSize = 5u;
|
||||
//
|
||||
// casIntfIO::casIntfIO()
|
||||
//
|
||||
casIntfIO::casIntfIO (const caNetAddr &addrIn) :
|
||||
sock (INVALID_SOCKET),
|
||||
addr (addrIn.getSockIP())
|
||||
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
sock ( INVALID_SOCKET ),
|
||||
addr ( addrIn.getSockIP() )
|
||||
{
|
||||
int status;
|
||||
osiSocklen_t addrSize;
|
||||
@@ -160,7 +169,7 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
struct sockaddr newAddr;
|
||||
SOCKET newSock;
|
||||
osiSocklen_t length;
|
||||
casStreamOS *pOS;
|
||||
casStreamOS * pOS;
|
||||
|
||||
length = ( osiSocklen_t ) sizeof ( newAddr );
|
||||
newSock = accept ( this->sock, & newAddr, & length );
|
||||
@@ -192,7 +201,7 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
if ( cas.getDebugLevel() > 0u ) {
|
||||
char pName[64u];
|
||||
|
||||
pOS->hostName ( pName, sizeof (pName) );
|
||||
pOS->hostName ( pName, sizeof ( pName ) );
|
||||
errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#include "server.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casStreamIO.h"
|
||||
|
||||
//
|
||||
// casStreamIO::casStreamIO()
|
||||
@@ -290,14 +291,10 @@ bufSizeT casStreamIO::optimumBufferSize ()
|
||||
int status;
|
||||
|
||||
/* 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)){
|
||||
n = sizeof ( size) ;
|
||||
status = getsockopt ( this->sock, SOL_SOCKET,
|
||||
SO_SNDBUF, (char *) & size, & n );
|
||||
if ( status < 0 || n != sizeof ( size ) ) {
|
||||
size = 0x400;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "osiSock.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#define caNetAddrSock
|
||||
#include "server.h"
|
||||
#include "ipIgnoreEntry.h"
|
||||
|
||||
void ipIgnoreEntry::show ( unsigned /* level */ ) const
|
||||
{
|
||||
@@ -57,7 +60,7 @@ void * ipIgnoreEntry::operator new ( size_t size,
|
||||
|
||||
#ifdef CXX_PLACEMENT_DELETE
|
||||
void ipIgnoreEntry::operator delete ( void * pCadaver,
|
||||
tsFreeList < class ipIgnoreEntry, 128 > & freeList ) epicsThrows(())
|
||||
tsFreeList < class ipIgnoreEntry, 128 > & freeList )
|
||||
{
|
||||
freeList.release ( pCadaver );
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <server.h>
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* float convert */
|
||||
|
||||
Reference in New Issue
Block a user