improved structure and thread safety

This commit is contained in:
Jeff Hill
2003-02-12 19:06:15 +00:00
parent 234c515b05
commit 644e6eb273
78 changed files with 2692 additions and 4957 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 )
{
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 ()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View 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

View File

@@ -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 &reg, 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 &regIn, 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 );
}

View File

@@ -47,26 +47,26 @@ public:
this->mask = 0u;
}
casEventMask (casEventRegistry &reg, const char *pName);
casEventMask ( casEventRegistry &reg, 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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#define epicsExportSharedSymbols
#include "casdef.h"
//

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

@@ -16,7 +16,8 @@
* 505 665 1831
*/
#include "server.h"
#define epicsExportSharedSymbols
#include "clientBufMemoryManager.h"
bufSizeT clientBufMemoryManager::maxSize () const
{

View 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

View File

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

View File

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

View 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

View File

@@ -15,9 +15,9 @@
#include <stdio.h>
#define epicsExportSharedSymbols
#include "casdef.h"
//
// ioBlocked::~ioBlocked()
//

View File

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

View File

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

View File

@@ -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 &regIn,
casEventMask maskIn, const char *pName);
virtual ~casEventMaskEntry();
void show (unsigned level) const;
virtual void destroy();
private:
casEventRegistry &reg;
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*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,10 +16,6 @@
*
*
*/
#include <server.h>
/************************************************************************/
/* float convert */