improved structure and thread safety
This commit is contained in:
@@ -8,12 +8,12 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// Example EPICS CA directory server
|
||||
// Example EPICS CA directory server
|
||||
//
|
||||
//
|
||||
// caServer
|
||||
// |
|
||||
// directoryServer
|
||||
// caServer
|
||||
// |
|
||||
// directoryServer
|
||||
//
|
||||
//
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#define caNetAddrSock
|
||||
#include "casdef.h"
|
||||
#include "epicsAssert.h"
|
||||
@@ -34,7 +35,7 @@
|
||||
|
||||
|
||||
#ifndef NELEMENTS
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
#endif
|
||||
|
||||
class directoryServer;
|
||||
@@ -44,24 +45,24 @@ class directoryServer;
|
||||
//
|
||||
class pvInfo {
|
||||
public:
|
||||
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
|
||||
addr(addrIn), pNext(pvInfo::pFirst)
|
||||
{
|
||||
pvInfo::pFirst = this;
|
||||
this->pName = new char [strlen(pNameIn)+1u];
|
||||
assert(this->pName);
|
||||
strcpy(this->pName, pNameIn);
|
||||
}
|
||||
|
||||
const struct sockaddr_in getAddr() const { return this->addr; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const pvInfo *getNext () const { return this->pNext; }
|
||||
static const pvInfo *getFirst () { return pvInfo::pFirst; }
|
||||
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
|
||||
addr(addrIn), pNext(pvInfo::pFirst)
|
||||
{
|
||||
pvInfo::pFirst = this;
|
||||
this->pName = new char [strlen(pNameIn)+1u];
|
||||
assert(this->pName);
|
||||
strcpy(this->pName, pNameIn);
|
||||
}
|
||||
|
||||
const struct sockaddr_in getAddr() const { return this->addr; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const pvInfo *getNext () const { return this->pNext; }
|
||||
static const pvInfo *getFirst () { return pvInfo::pFirst; }
|
||||
private:
|
||||
struct sockaddr_in addr;
|
||||
char *pName;
|
||||
const pvInfo *pNext;
|
||||
static const pvInfo *pFirst;
|
||||
struct sockaddr_in addr;
|
||||
char * pName;
|
||||
const pvInfo * pNext;
|
||||
static const pvInfo * pFirst;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -77,41 +78,39 @@ private:
|
||||
class pvEntry // X aCC 655
|
||||
: public stringId, public tsSLNode<pvEntry> {
|
||||
public:
|
||||
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
|
||||
inline ~pvEntry();
|
||||
inline ~pvEntry();
|
||||
|
||||
const pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
const pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
|
||||
private:
|
||||
const pvInfo &info;
|
||||
directoryServer &cas;
|
||||
const pvInfo &info;
|
||||
directoryServer &cas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// directoryServer
|
||||
//
|
||||
class directoryServer : public caServer {
|
||||
public:
|
||||
directoryServer (const char * const pvPrefix, unsigned aliasCount);
|
||||
~directoryServer();
|
||||
void show (unsigned level) const;
|
||||
pvExistReturn pvExistTest (const casCtx&, const char *pPVName);
|
||||
directoryServer ( const char * const pvPrefix, unsigned aliasCount );
|
||||
~directoryServer();
|
||||
void show ( unsigned level ) const;
|
||||
pvExistReturn pvExistTest ( const casCtx&, const char *pPVName );
|
||||
|
||||
void installAliasName (const pvInfo &info, const char *pAliasName);
|
||||
inline void removeAliasName(pvEntry &entry);
|
||||
void installAliasName ( const pvInfo &info, const char *pAliasName );
|
||||
inline void removeAliasName ( pvEntry &entry );
|
||||
|
||||
private:
|
||||
resTable<pvEntry,stringId> stringResTbl;
|
||||
resTable < pvEntry, stringId > stringResTbl;
|
||||
};
|
||||
|
||||
|
||||
@@ -120,9 +119,9 @@ private:
|
||||
//
|
||||
inline void directoryServer::removeAliasName(pvEntry &entry)
|
||||
{
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -130,7 +129,7 @@ inline void directoryServer::removeAliasName(pvEntry &entry)
|
||||
//
|
||||
inline pvEntry::~pvEntry()
|
||||
{
|
||||
this->cas.removeAliasName(*this);
|
||||
this->cas.removeAliasName(*this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -138,9 +137,9 @@ inline pvEntry::~pvEntry()
|
||||
//
|
||||
inline void pvEntry::destroy ()
|
||||
{
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
#include "directoryServer.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
LOCAL int parseDirectoryFile (const char *pFileName);
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName);
|
||||
static int parseDirectoryFile (const char *pFileName);
|
||||
static int parseDirectoryFP (FILE *pf, const char *pFileName);
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE (~0ul)
|
||||
@@ -109,7 +107,7 @@ extern int main (int argc, const char **argv)
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFile (const char *pFileName)
|
||||
static int parseDirectoryFile (const char *pFileName)
|
||||
{
|
||||
|
||||
FILE *pf;
|
||||
@@ -139,7 +137,7 @@ LOCAL int parseDirectoryFile (const char *pFileName)
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
static int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
{
|
||||
pvInfo *pPVI;
|
||||
char pvNameStr[128];
|
||||
@@ -193,8 +191,8 @@ LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
ipa.sin_port = 0u; // use the default CA server port
|
||||
}
|
||||
|
||||
pPVI = new pvInfo (pvNameStr, ipa);
|
||||
if (!pPVI) {
|
||||
pPVI = new pvInfo ( pvNameStr, ipa );
|
||||
if ( ! pPVI ) {
|
||||
fprintf (stderr, "Unable to allocate space for a new PV in \"%s\" with PV=\"%s\" host=\"%s\"\n",
|
||||
pFileName, pvNameStr, hostNameStr);
|
||||
return -1;
|
||||
|
||||
@@ -29,7 +29,7 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncReadIO ( ctx, *this, valueIn );
|
||||
pIO = new exAsyncReadIO ( this->cas, ctx, *this, valueIn );
|
||||
if (!pIO) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncWriteIO ( ctx, *this, valueIn );
|
||||
pIO = new exAsyncWriteIO ( this->cas, ctx, *this, valueIn );
|
||||
if ( ! pIO ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -62,10 +62,10 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
|
||||
//
|
||||
// exAsyncWriteIO::exAsyncWriteIO()
|
||||
//
|
||||
exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
const gdd &valueIn ) :
|
||||
exAsyncWriteIO::exAsyncWriteIO ( exServer & cas,
|
||||
const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ) :
|
||||
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( pvIn.getCAS()->createTimer () ), pValue(valueIn)
|
||||
timer ( cas.createTimer () ), pValue(valueIn)
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
@@ -76,9 +76,7 @@ exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
exAsyncWriteIO::~exAsyncWriteIO()
|
||||
{
|
||||
this->pv.removeIO();
|
||||
if ( this->pv.getCAS() ) {
|
||||
this->timer.destroy ();
|
||||
}
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -88,7 +86,7 @@ exAsyncWriteIO::~exAsyncWriteIO()
|
||||
epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
caStatus status;
|
||||
status = this->pv.update ( this->pValue );
|
||||
status = this->pv.update ( *this->pValue );
|
||||
this->postIOCompletion ( status );
|
||||
return noRestart;
|
||||
}
|
||||
@@ -96,10 +94,10 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* cur
|
||||
//
|
||||
// exAsyncReadIO::exAsyncReadIO()
|
||||
//
|
||||
exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
gdd &protoIn ) :
|
||||
exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
|
||||
exAsyncPV & pvIn, gdd & protoIn ) :
|
||||
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( pvIn.getCAS()->createTimer() ), pProto ( protoIn )
|
||||
timer ( cas.createTimer() ), pProto ( protoIn )
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
@@ -110,9 +108,7 @@ exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
|
||||
exAsyncReadIO::~exAsyncReadIO()
|
||||
{
|
||||
this->pv.removeIO ();
|
||||
if ( this->pv.getCAS() ) {
|
||||
this->timer.destroy ();
|
||||
}
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,8 +30,10 @@ class exFixedStringDestructor: public gddDestructor {
|
||||
//
|
||||
// exPV::exPV()
|
||||
//
|
||||
exPV::exPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
timer ( this->getCAS()->createTimer() ),
|
||||
exPV::exPV ( exServer & casIn, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
cas ( casIn ),
|
||||
timer ( cas.createTimer() ),
|
||||
info ( setup ),
|
||||
interest ( false ),
|
||||
preCreate ( preCreateFlag ),
|
||||
@@ -77,17 +79,14 @@ void exPV::destroy()
|
||||
//
|
||||
// exPV::update()
|
||||
//
|
||||
caStatus exPV::update(smartConstGDDPointer pValueIn)
|
||||
caStatus exPV::update ( const gdd & valueIn )
|
||||
{
|
||||
caServer *pCAS = this->getCAS();
|
||||
caStatus cas;
|
||||
|
||||
# if DEBUG
|
||||
printf("Setting %s too:\n", this->info.getName().string());
|
||||
valueIn.dump();
|
||||
# endif
|
||||
|
||||
cas = this->updateValue (pValueIn);
|
||||
caStatus cas = this->updateValue ( valueIn );
|
||||
if ( cas || ( ! this->pValue.valid() ) ) {
|
||||
return cas;
|
||||
}
|
||||
@@ -95,9 +94,10 @@ caStatus exPV::update(smartConstGDDPointer pValueIn)
|
||||
//
|
||||
// post a value change event
|
||||
//
|
||||
if (this->interest==true && pCAS!=NULL) {
|
||||
casEventMask select(pCAS->valueEventMask()|pCAS->logEventMask());
|
||||
this->postEvent (select, *this->pValue);
|
||||
caServer * pCAS = this->getCAS();
|
||||
if ( this->interest == true && pCAS != NULL ) {
|
||||
casEventMask select ( pCAS->valueEventMask() | pCAS->logEventMask() );
|
||||
this->postEvent ( select, valueIn );
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
@@ -129,16 +129,13 @@ aitEnum exPV::bestExternalType () const
|
||||
//
|
||||
// exPV::interestRegister()
|
||||
//
|
||||
caStatus exPV::interestRegister()
|
||||
caStatus exPV::interestRegister ()
|
||||
{
|
||||
caServer *pCAS = this->getCAS();
|
||||
|
||||
if ( ! pCAS ) {
|
||||
if ( ! this->getCAS() ) {
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
this->interest = true;
|
||||
|
||||
if ( this->scanOn && this->getScanPeriod() > 0.0 &&
|
||||
this->getScanPeriod() < this->timer.getExpireDelay() ) {
|
||||
this->timer.start ( *this, this->getScanPeriod() );
|
||||
@@ -174,7 +171,7 @@ void exPV::show ( unsigned level ) const
|
||||
//
|
||||
// exPV::initFT()
|
||||
//
|
||||
void exPV::initFT()
|
||||
void exPV::initFT ()
|
||||
{
|
||||
if ( exPV::hasBeenInitialized ) {
|
||||
return;
|
||||
@@ -203,7 +200,7 @@ void exPV::initFT()
|
||||
//
|
||||
// exPV::getPrecision()
|
||||
//
|
||||
caStatus exPV::getPrecision(gdd &prec)
|
||||
caStatus exPV::getPrecision ( gdd & prec )
|
||||
{
|
||||
prec.put(4u);
|
||||
return S_cas_success;
|
||||
@@ -212,7 +209,7 @@ caStatus exPV::getPrecision(gdd &prec)
|
||||
//
|
||||
// exPV::getHighLimit()
|
||||
//
|
||||
caStatus exPV::getHighLimit(gdd &value)
|
||||
caStatus exPV::getHighLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getHopr());
|
||||
return S_cas_success;
|
||||
@@ -221,7 +218,7 @@ caStatus exPV::getHighLimit(gdd &value)
|
||||
//
|
||||
// exPV::getLowLimit()
|
||||
//
|
||||
caStatus exPV::getLowLimit(gdd &value)
|
||||
caStatus exPV::getLowLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getLopr());
|
||||
return S_cas_success;
|
||||
@@ -230,7 +227,7 @@ caStatus exPV::getLowLimit(gdd &value)
|
||||
//
|
||||
// exPV::getUnits()
|
||||
//
|
||||
caStatus exPV::getUnits(gdd &units)
|
||||
caStatus exPV::getUnits( gdd & units )
|
||||
{
|
||||
aitString str("furlongs", aitStrRefConstImortal);
|
||||
units.put(str);
|
||||
@@ -283,7 +280,7 @@ caStatus exPV::getEnums ( gdd & enumsIn )
|
||||
//
|
||||
// exPV::getValue()
|
||||
//
|
||||
caStatus exPV::getValue(gdd &value)
|
||||
caStatus exPV::getValue ( gdd & value )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
@@ -309,18 +306,18 @@ caStatus exPV::getValue(gdd &value)
|
||||
// exPV::write()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::write (const casCtx &, const gdd &valueIn)
|
||||
caStatus exPV::write ( const casCtx &, const gdd & valueIn )
|
||||
{
|
||||
return this->update (valueIn);
|
||||
return this->update ( valueIn );
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::read()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::read (const casCtx &, gdd &protoIn)
|
||||
caStatus exPV::read ( const casCtx &, gdd & protoIn )
|
||||
{
|
||||
return this->ft.read (*this, protoIn);
|
||||
return this->ft.read ( *this, protoIn );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -328,11 +325,11 @@ caStatus exPV::read (const casCtx &, gdd &protoIn)
|
||||
//
|
||||
// for access control - optional
|
||||
//
|
||||
casChannel *exPV::createChannel (const casCtx &ctx,
|
||||
casChannel *exPV::createChannel ( const casCtx &ctx,
|
||||
const char * const /* pUserName */,
|
||||
const char * const /* pHostName */)
|
||||
const char * const /* pHostName */ )
|
||||
{
|
||||
return new exChannel (ctx);
|
||||
return new exChannel ( ctx );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -340,7 +337,7 @@ casChannel *exPV::createChannel (const casCtx &ctx,
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exFixedStringDestructor::run (void *pUntyped)
|
||||
void exFixedStringDestructor::run ( void * pUntyped )
|
||||
{
|
||||
aitFixedString *ps = (aitFixedString *) pUntyped;
|
||||
delete [] ps;
|
||||
|
||||
@@ -49,9 +49,9 @@ void exScalarPV::scan()
|
||||
// throughput under sunos4 because gettimeofday() is
|
||||
// slow)
|
||||
//
|
||||
this->currentTime = epicsTime::getCurrent();
|
||||
this->currentTime = epicsTime::getCurrent ();
|
||||
|
||||
pDD = new gddScalar (gddAppType_value, aitEnumFloat64);
|
||||
pDD = new gddScalar ( gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
@@ -59,27 +59,27 @@ void exScalarPV::scan()
|
||||
//
|
||||
// smart pointer class manages reference count after this point
|
||||
//
|
||||
gddStatus = pDD->unreference();
|
||||
assert (!gddStatus);
|
||||
gddStatus = pDD->unreference ();
|
||||
assert ( ! gddStatus );
|
||||
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
radians = ( rand () * 2.0 * myPI ) / RAND_MAX;
|
||||
if ( this->pValue.valid () ) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = tsMin (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = tsMax (newValue, limit);
|
||||
newValue += (float) ( sin (radians) / 10.0 );
|
||||
limit = (float) this->info.getHopr ();
|
||||
newValue = tsMin ( newValue, limit );
|
||||
limit = (float) this->info.getLopr ();
|
||||
newValue = tsMax ( newValue, limit );
|
||||
*pDD = newValue;
|
||||
aitTimeStamp gddts = this->currentTime;
|
||||
pDD->setTimeStamp (&gddts);
|
||||
status = this->update (pDD);
|
||||
pDD->setTimeStamp ( & gddts );
|
||||
status = this->update ( *pDD );
|
||||
if (status!=S_casApp_success) {
|
||||
errMessage (status, "scalar scan update failed\n");
|
||||
errMessage ( status, "scalar scan update failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,21 +95,25 @@ void exScalarPV::scan()
|
||||
// result in each value change events retaining an
|
||||
// independent value on the event queue.
|
||||
//
|
||||
caStatus exScalarPV::updateValue (smartConstGDDPointer pValueIn)
|
||||
caStatus exScalarPV::updateValue ( const gdd & valueIn )
|
||||
{
|
||||
if ( ! pValueIn.valid () ) {
|
||||
return S_casApp_undefined;
|
||||
}
|
||||
|
||||
//
|
||||
// Really no need to perform this check since the
|
||||
// server lib verifies that all requests are in range
|
||||
//
|
||||
if (!pValueIn->isScalar()) {
|
||||
if ( ! valueIn.isScalar() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
this->pValue = pValueIn;
|
||||
if ( ! pValue.valid () ) {
|
||||
this->pValue = new gddScalar (
|
||||
gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pValue.valid () ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
|
||||
this->pValue->put ( & valueIn );
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -44,9 +44,10 @@ pvInfo exServer::bloaty (-1.0, "bloaty", 10.0f, -10.0f, aitEnumFloat64, excasIoS
|
||||
// exServer::exServer()
|
||||
//
|
||||
exServer::exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOnIn ) :
|
||||
simultAsychIOCount (0u),
|
||||
scanOn (scanOnIn)
|
||||
unsigned aliasCount, bool scanOnIn,
|
||||
bool asyncScan ) :
|
||||
pTimerQueue ( 0 ), simultAsychIOCount ( 0u ),
|
||||
scanOn ( scanOnIn )
|
||||
{
|
||||
unsigned i;
|
||||
exPV *pPV;
|
||||
@@ -58,6 +59,16 @@ exServer::exServer ( const char * const pvPrefix,
|
||||
|
||||
exPV::initFT();
|
||||
|
||||
if ( asyncScan ) {
|
||||
unsigned timerPriotity;
|
||||
epicsThreadBooleanStatus etbs = epicsThreadLowestPriorityLevelAbove (
|
||||
epicsThreadGetPrioritySelf (), & timerPriotity );
|
||||
if ( etbs != epicsThreadBooleanStatusSuccess ) {
|
||||
timerPriotity = epicsThreadGetPrioritySelf ();
|
||||
}
|
||||
this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, timerPriotity );
|
||||
}
|
||||
|
||||
//
|
||||
// pre-create all of the simple PVs that this server will export
|
||||
//
|
||||
@@ -236,10 +247,31 @@ pvAttachReturn exServer::pvAttach // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::setDebugLevel ()
|
||||
//
|
||||
void exServer::setDebugLevel ( unsigned level )
|
||||
{
|
||||
this->caServer::setDebugLevel ( level );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::createTimer ()
|
||||
//
|
||||
class epicsTimer & exServer::createTimer ()
|
||||
{
|
||||
if ( this->pTimerQueue ) {
|
||||
return this->pTimerQueue->createTimer ();
|
||||
}
|
||||
else {
|
||||
return this->caServer::createTimer ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// pvInfo::createPV()
|
||||
//
|
||||
exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
exPV *pvInfo::createPV ( exServer & cas,
|
||||
bool preCreateFlag, bool scanOn )
|
||||
{
|
||||
if (this->pPV) {
|
||||
@@ -256,10 +288,10 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
if (this->elementCount==1u) {
|
||||
switch (this->ioType){
|
||||
case excasIoSync:
|
||||
pNewPV = new exScalarPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
case excasIoAsync:
|
||||
pNewPV = new exAsyncPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exAsyncPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
default:
|
||||
pNewPV = NULL;
|
||||
@@ -268,7 +300,7 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
|
||||
}
|
||||
else {
|
||||
if ( this->ioType == excasIoSync ) {
|
||||
pNewPV = new exVectorPV ( *this, preCreateFlag, scanOn );
|
||||
pNewPV = new exVectorPV ( cas, *this, preCreateFlag, scanOn );
|
||||
}
|
||||
else {
|
||||
pNewPV = NULL;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "gddAppFuncTable.h"
|
||||
#include "epicsTimer.h"
|
||||
#include "casdef.h"
|
||||
@@ -124,7 +125,8 @@ private:
|
||||
class exPV : public casPV, public epicsTimerNotify,
|
||||
public tsSLNode < exPV > {
|
||||
public:
|
||||
exPV ( pvInfo & setup, bool preCreateFlag, bool scanOn );
|
||||
exPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOn );
|
||||
virtual ~exPV();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
@@ -158,7 +160,7 @@ public:
|
||||
//
|
||||
// This gets called when the pv gets a new value
|
||||
//
|
||||
caStatus update ( smartConstGDDPointer pValue );
|
||||
caStatus update ( const gdd & );
|
||||
|
||||
//
|
||||
// Gets called when we add noise to the current value
|
||||
@@ -190,7 +192,8 @@ public:
|
||||
const char * const pHostName );
|
||||
|
||||
protected:
|
||||
smartConstGDDPointer pValue;
|
||||
smartGDDPointer pValue;
|
||||
exServer & cas;
|
||||
epicsTimer & timer;
|
||||
pvInfo & info;
|
||||
bool interest;
|
||||
@@ -198,7 +201,7 @@ protected:
|
||||
bool scanOn;
|
||||
static epicsTime currentTime;
|
||||
|
||||
virtual caStatus updateValue ( smartConstGDDPointer pValue ) = 0;
|
||||
virtual caStatus updateValue ( const gdd & ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
@@ -229,11 +232,13 @@ private:
|
||||
//
|
||||
class exScalarPV : public exPV {
|
||||
public:
|
||||
exScalarPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( setup, preCreateFlag, scanOnIn) {}
|
||||
exScalarPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
private:
|
||||
caStatus updateValue (smartConstGDDPointer pValue);
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
@@ -241,36 +246,45 @@ private:
|
||||
//
|
||||
class exVectorPV : public exPV {
|
||||
public:
|
||||
exVectorPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( setup, preCreateFlag, scanOnIn) {}
|
||||
exVectorPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
|
||||
unsigned maxDimension() const;
|
||||
aitIndex maxBound (unsigned dimension) const;
|
||||
|
||||
private:
|
||||
caStatus updateValue (smartConstGDDPointer pValue);
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
// exServer
|
||||
//
|
||||
class exServer : public caServer {
|
||||
class exServer : private caServer {
|
||||
public:
|
||||
exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOn );
|
||||
unsigned aliasCount, bool scanOn,
|
||||
bool asyncScan );
|
||||
~exServer ();
|
||||
void show ( unsigned level ) const;
|
||||
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
|
||||
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
|
||||
void installAliasName ( pvInfo & info, const char * pAliasName );
|
||||
inline void removeAliasName ( pvEntry & entry );
|
||||
void removeIO();
|
||||
void removeIO ();
|
||||
void removeAliasName ( pvEntry & entry );
|
||||
|
||||
class epicsTimer & createTimer ();
|
||||
void setDebugLevel ( unsigned level );
|
||||
|
||||
private:
|
||||
resTable < pvEntry, stringId > stringResTbl;
|
||||
epicsTimerQueueActive * pTimerQueue;
|
||||
unsigned simultAsychIOCount;
|
||||
bool scanOn;
|
||||
|
||||
void installAliasName ( pvInfo & info, const char * pAliasName );
|
||||
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
|
||||
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
|
||||
|
||||
//
|
||||
// list of pre-created PVs
|
||||
//
|
||||
@@ -292,7 +306,8 @@ private:
|
||||
//
|
||||
class exAsyncPV : public exScalarPV {
|
||||
public:
|
||||
exAsyncPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn );
|
||||
exAsyncPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn );
|
||||
caStatus read ( const casCtx & ctxIn, gdd & protoIn );
|
||||
caStatus write ( const casCtx & ctxIn, const gdd & value );
|
||||
void removeIO();
|
||||
@@ -318,7 +333,7 @@ private:
|
||||
//
|
||||
class exAsyncWriteIO : public casAsyncWriteIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncWriteIO ( const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn );
|
||||
exAsyncWriteIO ( exServer &, const casCtx & ctxIn, exAsyncPV &, const gdd & );
|
||||
~exAsyncWriteIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
@@ -332,7 +347,7 @@ private:
|
||||
//
|
||||
class exAsyncReadIO : public casAsyncReadIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncReadIO ( const casCtx & ctxIn, exAsyncPV & pvIn, gdd & protoIn );
|
||||
exAsyncReadIO ( exServer &, const casCtx &, exAsyncPV &, gdd & );
|
||||
virtual ~exAsyncReadIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
@@ -519,9 +534,9 @@ inline void exServer::removeIO()
|
||||
}
|
||||
}
|
||||
|
||||
inline exAsyncPV::exAsyncPV ( pvInfo & setup, bool preCreateFlag,
|
||||
bool scanOnIn ) :
|
||||
exScalarPV ( setup, preCreateFlag, scanOnIn ),
|
||||
inline exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exScalarPV ( cas, setup, preCreateFlag, scanOnIn ),
|
||||
simultAsychIOCount ( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,8 +141,8 @@ void exVectorPV::scan()
|
||||
*(pF++) = newValue;
|
||||
}
|
||||
|
||||
status = this->update (pDD);
|
||||
if (status!=S_casApp_success) {
|
||||
status = this->update ( *pDD );
|
||||
if ( status != S_casApp_success ) {
|
||||
errMessage (status, "vector scan update failed\n");
|
||||
}
|
||||
}
|
||||
@@ -161,16 +161,8 @@ void exVectorPV::scan()
|
||||
// this may result in too much memory consumtion on
|
||||
// the event queue.
|
||||
//
|
||||
caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
caStatus exVectorPV::updateValue ( const gdd & value )
|
||||
{
|
||||
gddStatus gdds;
|
||||
smartGDDPointer pNewValue;
|
||||
exVecDestructor *pDest;
|
||||
unsigned i;
|
||||
|
||||
if ( ! pValueIn.valid () ) {
|
||||
return S_casApp_undefined;
|
||||
}
|
||||
|
||||
//
|
||||
// Check bounds of incoming request
|
||||
@@ -180,50 +172,47 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// Perhaps much of this is unnecessary since the
|
||||
// server lib checks the bounds of all requests
|
||||
//
|
||||
if (pValueIn->isAtomic()) {
|
||||
if (pValueIn->dimension()!=1u) {
|
||||
if ( value.isAtomic()) {
|
||||
if ( value.dimension() != 1u ) {
|
||||
return S_casApp_badDimension;
|
||||
}
|
||||
const gddBounds* pb = pValueIn->getBounds();
|
||||
if (pb[0u].first()!=0u) {
|
||||
const gddBounds* pb = value.getBounds ();
|
||||
if ( pb[0u].first() != 0u ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
else if (pb[0u].size()>this->info.getElementCount()) {
|
||||
else if ( pb[0u].size() > this->info.getElementCount() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
}
|
||||
else if (!pValueIn->isScalar()) {
|
||||
else if ( ! value.isScalar() ) {
|
||||
//
|
||||
// no containers
|
||||
//
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
aitFloat64 *pF;
|
||||
int gddStatus;
|
||||
|
||||
|
||||
//
|
||||
// Create a new array data descriptor
|
||||
// (so that old values that may be referenced on the
|
||||
// event queue are not replaced)
|
||||
//
|
||||
pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount());
|
||||
if ( ! pNewValue.valid () ) {
|
||||
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount() ) );
|
||||
if ( ! pNewValue.valid() ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// smart pointer class takes care of the reference count
|
||||
// from here down
|
||||
//
|
||||
gddStatus = pNewValue->unreference();
|
||||
assert (!gddStatus);
|
||||
|
||||
gddStatus gdds = pNewValue->unreference( );
|
||||
assert ( ! gdds );
|
||||
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
pF = new aitFloat64 [this->info.getElementCount()];
|
||||
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
@@ -233,11 +222,11 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// if no old values exist
|
||||
//
|
||||
unsigned count = this->info.getElementCount();
|
||||
for ( i = 0u; i < count; i++ ) {
|
||||
for ( unsigned i = 0u; i < count; i++ ) {
|
||||
pF[i] = 0.0f;
|
||||
}
|
||||
|
||||
pDest = new exVecDestructor;
|
||||
exVecDestructor * pDest = new exVecDestructor;
|
||||
if (!pDest) {
|
||||
delete [] pF;
|
||||
return S_casApp_noMemory;
|
||||
@@ -247,13 +236,13 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
// install the buffer into the DD
|
||||
// (do this before we increment pF)
|
||||
//
|
||||
pNewValue->putRef(pF, pDest);
|
||||
pNewValue->putRef ( pF, pDest );
|
||||
|
||||
//
|
||||
// copy in the values that they are writing
|
||||
//
|
||||
gdds = pNewValue->put( & (*pValueIn) );
|
||||
if (gdds) {
|
||||
gdds = pNewValue->put( & value );
|
||||
if ( gdds ) {
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
|
||||
@@ -267,8 +256,8 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exVecDestructor::run (void *pUntyped)
|
||||
void exVecDestructor::run ( void *pUntyped )
|
||||
{
|
||||
aitFloat32 *pf = (aitFloat32 *) pUntyped;
|
||||
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
|
||||
delete [] pf;
|
||||
}
|
||||
|
||||
@@ -25,37 +25,40 @@ extern int main (int argc, const char **argv)
|
||||
double executionTime;
|
||||
char pvPrefix[128] = "";
|
||||
unsigned aliasCount = 1u;
|
||||
unsigned scanOnAsUnsignedInt = true;
|
||||
unsigned scanOn = true;
|
||||
unsigned syncScan = true;
|
||||
char arraySize[64] = "";
|
||||
bool scanOn;
|
||||
bool forever = true;
|
||||
int i;
|
||||
|
||||
for ( i = 1; i < argc; i++ ) {
|
||||
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
|
||||
if ( sscanf(argv[i], "-d %u", & debugLevel ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-t %lf", &executionTime)==1) {
|
||||
if ( sscanf ( argv[i],"-t %lf", & executionTime ) == 1 ) {
|
||||
forever = false;
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-p %127s", pvPrefix)==1) {
|
||||
if ( sscanf ( argv[i], "-p %127s", pvPrefix ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-c %u", &aliasCount)==1) {
|
||||
if ( sscanf ( argv[i],"-c %u", & aliasCount ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-s %u", &scanOnAsUnsignedInt)==1) {
|
||||
if ( sscanf ( argv[i],"-s %u", & scanOn ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-a %63s", arraySize)==1) {
|
||||
if ( sscanf ( argv[i],"-a %63s", arraySize ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-ss %u", & syncScan ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
printf ("\"%s\"?\n", argv[i]);
|
||||
printf (
|
||||
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> "
|
||||
"-c<numbered alias count> -s<1=scan on (default), 0=scan off]> "
|
||||
"-a<max array size>]\n",
|
||||
"-c<numbered alias count> -s<1=scan on (default), 0=scan off> "
|
||||
"-ss<1=synchronous scan (default), 0=asynchronous scan>]\n",
|
||||
argv[0]);
|
||||
|
||||
return (1);
|
||||
@@ -65,15 +68,9 @@ extern int main (int argc, const char **argv)
|
||||
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", arraySize );
|
||||
}
|
||||
|
||||
if (scanOnAsUnsignedInt) {
|
||||
scanOn = true;
|
||||
}
|
||||
else {
|
||||
scanOn = false;
|
||||
}
|
||||
|
||||
try {
|
||||
pCAS = new exServer ( pvPrefix, aliasCount, scanOn );
|
||||
pCAS = new exServer ( pvPrefix, aliasCount,
|
||||
scanOn != 0, syncScan == 0 );
|
||||
}
|
||||
catch ( ... ) {
|
||||
errlogPrintf ( "Server initialization error\n" );
|
||||
|
||||
Reference in New Issue
Block a user