Merged the pcas-vararray-3.14 branch, with fixes and notes

This commit is contained in:
Andrew Johnson
2016-10-20 12:22:00 -05:00
9 changed files with 203 additions and 181 deletions
+7 -2
View File
@@ -40,8 +40,13 @@ class casIntfOS;
class casMonitor;
class casChannelI;
caStatus convertContainerMemberToAtomic ( class gdd & dd,
aitUint32 appType, aitUint32 elemCount );
caStatus convertContainerMemberToAtomic (class gdd & dd,
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount);
// Keep the old signature for backward compatibility
inline caStatus convertContainerMemberToAtomic (class gdd & dd,
aitUint32 appType, aitUint32 elemCount)
{ return convertContainerMemberToAtomic(dd, appType, elemCount, elemCount); }
class caServerI :
public caServerIO,
+47 -43
View File
@@ -409,17 +409,8 @@ caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
//
// element count out of range ?
//
if ( allowdyn && ctx.msg.m_count==0 &&
CA_V413 ( this->minor_version_number ) ) {
// Hack
// Since GDD interface doesn't support variable sized arrays
// we present dynamic requests as max size.
// This allows PCAS to claim support for dynamic arrays w/o
// going to the trouble of fixing GDD.
ctx.msg.m_count = pChan->getPVI().nativeCount();
}
else if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
ctx.msg.m_count == 0u ) {
if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
return ECA_BADCOUNT;
}
@@ -452,7 +443,7 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard )
casChannelI * pChan;
{
caStatus status = this->verifyRequest ( pChan, true );
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
if ( pChan ) {
return this->sendErr ( guard, mp, pChan->getCID(),
@@ -539,11 +530,15 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
pChan->getCID(), status, ECA_GETFAIL );
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;
void * pPayload;
{
unsigned payloadSize = dbr_size_n ( msg.m_dataType, msg.m_count );
unsigned payloadSize = dbr_size_n ( msg.m_dataType, count );
caStatus localStatus = this->out.copyInHeader ( msg.m_cmmd, payloadSize,
msg.m_dataType, msg.m_count, pChan->getCID (),
msg.m_dataType, count, pChan->getCID (),
msg.m_available, & pPayload );
if ( localStatus ) {
if ( localStatus==S_cas_hugeRequest ) {
@@ -559,21 +554,21 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
// (places the data in network format)
//
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr(
pPayload, msg.m_count, desc, pChan->enumStringTable() );
pPayload, count, desc, pChan->enumStringTable() );
if ( mapDBRStatus < 0 ) {
desc.dump ();
errPrintf ( S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u",
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
pChan->getPVI().getName(), msg.m_dataType, count );
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_badBounds, ECA_GETFAIL );
}
int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
}
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
@@ -593,7 +588,7 @@ caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard
casChannelI * pChan;
{
caStatus status = this->verifyRequest ( pChan, true );
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
return this->readNotifyFailureResponse ( guard, * mp, status );
}
@@ -664,11 +659,15 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
return ecaStatus;
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;
void *pPayload;
{
unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count );
unsigned size = dbr_size_n ( msg.m_dataType, count );
caStatus status = this->out.copyInHeader ( msg.m_cmmd, size,
msg.m_dataType, msg.m_count, ECA_NORMAL,
msg.m_dataType, count, ECA_NORMAL,
msg.m_available, & pPayload );
if ( status ) {
if ( status == S_cas_hugeRequest ) {
@@ -683,23 +682,23 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
// convert gdd to db_access type
//
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload,
msg.m_count, desc, pChan->enumStringTable() );
count, desc, pChan->enumStringTable() );
if ( mapDBRStatus < 0 ) {
desc.dump();
errPrintf ( S_cas_badBounds, __FILE__, __LINE__,
"- get notify with PV=%s type=%u count=%u",
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
pChan->getPVI().getName(), msg.m_dataType, count );
return this->readNotifyFailureResponse ( guard, msg, ECA_NOCONVERT );
}
int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
}
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
@@ -735,8 +734,8 @@ caStatus casStrmClient::readNotifyFailureResponse (
// to be more efficent if it discovers that the source has less data
// than the destination)
//
caStatus convertContainerMemberToAtomic ( gdd & dd,
aitUint32 appType, aitUint32 elemCount )
caStatus convertContainerMemberToAtomic ( gdd & dd,
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount )
{
gdd * pVal;
if ( dd.isContainer() ) {
@@ -763,13 +762,13 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
return S_cas_badType;
}
if ( elemCount <= 1 ) {
if ( nativeCount <= 1 ) {
return S_cas_success;
}
// convert to atomic
gddBounds bds;
bds.setSize ( elemCount );
bds.setSize ( requestedCount );
bds.setFirst ( 0u );
pVal->setDimension ( 1u, & bds );
return S_cas_success;
@@ -778,9 +777,9 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
//
// createDBRDD ()
//
static caStatus createDBRDD ( unsigned dbrType,
unsigned elemCount, gdd * & pDD )
{
static caStatus createDBRDD ( unsigned dbrType,
unsigned requestedCount, unsigned nativeCount, gdd * & pDD )
{
/*
* DBR type has already been checked, but it is possible
* that "gddDbrToAit" will not track with changes in
@@ -807,7 +806,7 @@ static caStatus createDBRDD ( unsigned dbrType,
// fix the value element count
caStatus status = convertContainerMemberToAtomic (
*pDescRet, gddAppType_value, elemCount );
*pDescRet, gddAppType_value, requestedCount, nativeCount );
if ( status != S_cas_success ) {
pDescRet->unreference ();
return status;
@@ -857,11 +856,15 @@ caStatus casStrmClient::monitorResponse (
casChannelI & chan, const caHdrLargeArray & msg,
const gdd & desc, const caStatus completionStatus )
{
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;
void * pPayload = 0;
{
ca_uint32_t size = dbr_size_n ( msg.m_dataType, msg.m_count );
ca_uint32_t size = dbr_size_n ( msg.m_dataType, count );
caStatus status = out.copyInHeader ( msg.m_cmmd, size,
msg.m_dataType, msg.m_count, ECA_NORMAL,
msg.m_dataType, count, ECA_NORMAL,
msg.m_available, & pPayload );
if ( status ) {
if ( status == S_cas_hugeRequest ) {
@@ -879,7 +882,8 @@ caStatus casStrmClient::monitorResponse (
gdd * pDBRDD = 0;
if ( completionStatus == S_cas_success ) {
caStatus status = createDBRDD ( msg.m_dataType, msg.m_count, pDBRDD );
caStatus status = createDBRDD ( msg.m_dataType, count,
chan.getPVI().nativeCount(), pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
@@ -900,7 +904,7 @@ caStatus casStrmClient::monitorResponse (
pDBRDD->unreference ();
errPrintf ( S_cas_noConvert, __FILE__, __LINE__,
"no conversion between event app type=%d and DBR type=%d Element count=%d",
desc.applicationType (), msg.m_dataType, msg.m_count);
desc.applicationType (), msg.m_dataType, count);
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
}
}
@@ -923,14 +927,14 @@ caStatus casStrmClient::monitorResponse (
}
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr (
pPayload, msg.m_count, *pDBRDD, chan.enumStringTable() );
pPayload, count, *pDBRDD, chan.enumStringTable() );
if ( mapDBRStatus < 0 ) {
pDBRDD->unreference ();
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
}
int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
pDBRDD->unreference ();
return this->sendErrWithEpicsStatus (
@@ -940,7 +944,7 @@ caStatus casStrmClient::monitorResponse (
//
// force string message size to be the true size
//
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
ca_uint32_t reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
@@ -1948,7 +1952,7 @@ caStatus casStrmClient::eventAddAction (
casChannelI *pciu;
{
caStatus status = casStrmClient::verifyRequest ( pciu, true );
caStatus status = casStrmClient::verifyRequest ( pciu, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
if ( pciu ) {
return this->sendErr ( guard, mp,
@@ -2609,8 +2613,8 @@ caStatus casStrmClient::read ()
{
gdd * pDD = 0;
caStatus status = createDBRDD ( pHdr->m_dataType,
pHdr->m_count, pDD );
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
this->ctx.getChannel()->getPVI().nativeCount(), pDD );
if ( status != S_cas_success ) {
return status;
}
+3 -2
View File
@@ -1355,8 +1355,9 @@ gddStatus gdd::put ( const gdd * dd )
}
aitUint32 srcAvailSize = srcElemCount - unusedSrcBelow;
if ( srcAvailSize > this->getBounds()->size() ) {
srcCopySize = this->getBounds()->size();
aitUint32 destSize = this->getBounds()->size();
if ( destSize > 0 && srcAvailSize > destSize ) {
srcCopySize = destSize;
}
else {
srcCopySize = srcAvailSize;
+52 -53
View File
@@ -3,9 +3,8 @@
* 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.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
@@ -30,23 +29,23 @@ exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup,
//
caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
{
exAsyncReadIO *pIO;
if ( this->simultAsychReadIOCount >= this->cas.maxSimultAsyncIO () ) {
return S_casApp_postponeAsyncIO;
}
exAsyncReadIO *pIO;
pIO = new exAsyncReadIO ( this->cas, ctx,
*this, valueIn, this->asyncDelay );
if ( ! pIO ) {
if ( this->simultAsychReadIOCount >= this->cas.maxSimultAsyncIO () ) {
return S_casApp_postponeAsyncIO;
}
pIO = new exAsyncReadIO ( this->cas, ctx,
*this, valueIn, this->asyncDelay );
if ( ! pIO ) {
if ( this->simultAsychReadIOCount > 0 ) {
return S_casApp_postponeAsyncIO;
}
else {
return S_casApp_noMemory;
return S_casApp_noMemory;
}
}
this->simultAsychReadIOCount++;
}
this->simultAsychReadIOCount++;
return S_casApp_asyncCompletion;
}
@@ -54,24 +53,24 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
// exAsyncPV::writeNotify()
//
caStatus exAsyncPV::writeNotify ( const casCtx &ctx, const gdd &valueIn )
{
if ( this->simultAsychWriteIOCount >= this->cas.maxSimultAsyncIO() ) {
return S_casApp_postponeAsyncIO;
}
{
if ( this->simultAsychWriteIOCount >= this->cas.maxSimultAsyncIO() ) {
return S_casApp_postponeAsyncIO;
}
exAsyncWriteIO * pIO = new
exAsyncWriteIO * pIO = new
exAsyncWriteIO ( this->cas, ctx, *this,
valueIn, this->asyncDelay );
if ( ! pIO ) {
valueIn, this->asyncDelay );
if ( ! pIO ) {
if ( this->simultAsychReadIOCount > 0 ) {
return S_casApp_postponeAsyncIO;
}
else {
return S_casApp_noMemory;
return S_casApp_noMemory;
}
}
this->simultAsychWriteIOCount++;
return S_casApp_asyncCompletion;
this->simultAsychWriteIOCount++;
return S_casApp_asyncCompletion;
}
//
@@ -79,24 +78,24 @@ caStatus exAsyncPV::writeNotify ( const casCtx &ctx, const gdd &valueIn )
//
caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
{
// implement the discard intermediate values, but last value
// implement the discard intermediate values, but last value
// sent always applied behavior that IOCs provide excepting
// that we will alow N requests to pend instead of a limit
// of only one imposed in the IOC
if ( this->simultAsychWriteIOCount >= this->cas.maxSimultAsyncIO() ) {
if ( this->simultAsychWriteIOCount >= this->cas.maxSimultAsyncIO() ) {
pStandbyValue.set ( & valueIn );
return S_casApp_success;
}
exAsyncWriteIO * pIO = new
exAsyncWriteIO ( this->cas, ctx, *this,
valueIn, this->asyncDelay );
if ( ! pIO ) {
pStandbyValue.set ( & valueIn );
return S_casApp_success;
return S_casApp_success;
}
this->simultAsychWriteIOCount++;
return S_casApp_asyncCompletion;
exAsyncWriteIO * pIO = new
exAsyncWriteIO ( this->cas, ctx, *this,
valueIn, this->asyncDelay );
if ( ! pIO ) {
pStandbyValue.set ( & valueIn );
return S_casApp_success;
}
this->simultAsychWriteIOCount++;
return S_casApp_asyncCompletion;
}
// Implementing a specialized update for exAsyncPV
@@ -150,7 +149,7 @@ void exAsyncPV::removeWriteIO ()
exAsyncWriteIO::exAsyncWriteIO ( exServer & cas,
const casCtx & ctxIn, exAsyncPV & pvIn,
const gdd & valueIn, double asyncDelay ) :
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
timer ( cas.createTimer () ), pValue(valueIn)
{
this->timer.start ( *this, asyncDelay );
@@ -168,7 +167,7 @@ exAsyncWriteIO::~exAsyncWriteIO()
if ( this->pValue.valid () ) {
this->pv.updateFromAsyncWrite ( *this->pValue );
}
this->pv.removeWriteIO();
this->pv.removeWriteIO();
}
//
@@ -179,9 +178,9 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::
expire ( const epicsTime & /* currentTime */ )
{
assert ( this->pValue.valid () );
caStatus status = this->pv.updateFromAsyncWrite ( *this->pValue );
this->pValue.set ( 0 );
this->postIOCompletion ( status );
caStatus status = this->pv.updateFromAsyncWrite ( *this->pValue );
this->pValue.set ( 0 );
this->postIOCompletion ( status );
return noRestart;
}
@@ -191,7 +190,7 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::
exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
exAsyncPV & pvIn, gdd & protoIn,
double asyncDelay ) :
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
timer ( cas.createTimer() ), pProto ( protoIn )
{
this->timer.start ( *this, asyncDelay );
@@ -202,7 +201,7 @@ exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
//
exAsyncReadIO::~exAsyncReadIO()
{
this->pv.removeReadIO ();
this->pv.removeReadIO ();
this->timer.destroy ();
}
@@ -213,16 +212,16 @@ exAsyncReadIO::~exAsyncReadIO()
epicsTimerNotify::expireStatus
exAsyncReadIO::expire ( const epicsTime & /* currentTime */ )
{
//
// map between the prototype in and the
// current value
//
caStatus status = this->pv.exPV::readNoCtx ( this->pProto );
//
// map between the prototype in and the
// current value
//
caStatus status = this->pv.exPV::readNoCtx ( this->pProto );
//
// post IO completion
//
this->postIOCompletion ( status, *this->pProto );
//
// post IO completion
//
this->postIOCompletion ( status, *this->pProto );
return noRestart;
}
+3 -4
View File
@@ -3,9 +3,8 @@
* 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.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
// Example EPICS CA server
@@ -42,7 +41,7 @@ exPV::exPV ( exServer & casIn, pvInfo & setup,
//
// no dataless PV allowed
//
assert (this->info.getElementCount()>=1u);
assert (this->info.getCapacity()>=1u);
//
// start a very slow background scan
+3 -4
View File
@@ -3,9 +3,8 @@
* 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.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
// fileDescriptorManager.process(delay);
@@ -304,7 +303,7 @@ exPV *pvInfo::createPV ( exServer & cas, bool preCreateFlag,
// depending on the io type and the number
// of elements
//
if (this->elementCount==1u) {
if (this->capacity==1u) {
switch (this->ioType){
case excasIoSync:
pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn );
+26 -14
View File
@@ -3,9 +3,8 @@
* 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.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
// Example EPICS CA server
@@ -76,8 +75,10 @@ public:
double getLopr () const;
aitEnum getType () const;
excasIoType getIOType () const;
unsigned getElementCount () const;
void unlinkPV ();
unsigned getCapacity () const;
unsigned getElementCount () const;
void setElementCount (unsigned);
void unlinkPV ();
exPV *createPV ( exServer & exCAS, bool preCreateFlag,
bool scanOn, double asyncDelay );
void deletePV ();
@@ -88,7 +89,8 @@ private:
const double lopr;
aitEnum type;
const excasIoType ioType;
const unsigned elementCount;
const unsigned capacity;
unsigned elementCount;
exPV * pPV;
pvInfo & operator = ( const pvInfo & );
};
@@ -441,8 +443,8 @@ inline pvInfo::pvInfo ( double scanPeriodIn, const char *pNameIn,
scanPeriod ( scanPeriodIn ), pName ( pNameIn ),
hopr ( hoprIn ), lopr ( loprIn ), type ( typeIn ),
ioType ( ioTypeIn ), elementCount ( countIn ),
pPV ( 0 )
ioType ( ioTypeIn ), capacity ( countIn ),
elementCount ( 0 ), pPV ( 0 )
{
}
@@ -454,8 +456,8 @@ inline pvInfo::pvInfo ( const pvInfo & copyIn ) :
scanPeriod ( copyIn.scanPeriod ), pName ( copyIn.pName ),
hopr ( copyIn.hopr ), lopr ( copyIn.lopr ), type ( copyIn.type ),
ioType ( copyIn.ioType ), elementCount ( copyIn.elementCount ),
pPV ( copyIn.pPV )
ioType ( copyIn.ioType ), capacity ( copyIn.capacity ),
elementCount ( copyIn.elementCount ), pPV ( copyIn.pPV )
{
}
@@ -509,12 +511,22 @@ inline excasIoType pvInfo::getIOType () const
return this->ioType;
}
inline unsigned pvInfo::getElementCount () const
{
return this->elementCount;
inline unsigned pvInfo::getCapacity () const
{
return this->capacity;
}
inline void pvInfo::unlinkPV ()
inline unsigned pvInfo::getElementCount () const
{
return this->elementCount;
}
inline void pvInfo::setElementCount (unsigned newCount)
{
this->elementCount = newCount;
}
inline void pvInfo::unlinkPV ()
{
this->pPV = NULL;
}
+54 -56
View File
@@ -3,9 +3,8 @@
* 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.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "exServer.h"
@@ -48,7 +47,7 @@ unsigned exVectorPV::maxDimension() const
aitIndex exVectorPV::maxBound (unsigned dimension) const // X aCC 361
{
if (dimension==0u) {
return this->info.getElementCount();
return this->info.getCapacity();
}
else {
return 0u;
@@ -60,26 +59,21 @@ aitIndex exVectorPV::maxBound (unsigned dimension) const // X aCC 361
//
void exVectorPV::scan()
{
caStatus status;
double radians;
smartGDDPointer pDD;
aitFloat32 *pF, *pFE;
const aitFloat32 *pCF;
float newValue;
float limit;
exVecDestructor *pDest;
int gddStatus;
static epicsTime startTime = epicsTime::getCurrent();
//
// update current time (so we are not required to do
// this every time that we write the PV which impacts
// throughput under sunos4 because gettimeofday() is
// slow)
// update current time
//
this->currentTime = epicsTime::getCurrent();
pDD = new gddAtomic (gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount());
// demonstrate a changing array size
unsigned ramp = 15 & (unsigned) (this->currentTime - startTime);
unsigned newSize = this->info.getCapacity();
if (newSize > ramp) {
newSize -= ramp;
}
smartGDDPointer pDD = new gddAtomic (gddAppType_value, aitEnumFloat64,
1u, newSize);
if ( ! pDD.valid () ) {
return;
}
@@ -87,18 +81,18 @@ void exVectorPV::scan()
//
// smart pointer class manages reference count after this point
//
gddStatus = pDD->unreference();
assert (!gddStatus);
gddStatus gdds = pDD->unreference();
assert(!gdds);
//
// allocate array buffer
//
pF = new aitFloat32 [this->info.getElementCount()];
aitFloat64 * pF = new aitFloat64 [newSize];
if (!pF) {
return;
}
pDest = new exVecDestructor;
exVecDestructor * pDest = new exVecDestructor;
if (!pDest) {
delete [] pF;
return;
@@ -114,37 +108,39 @@ void exVectorPV::scan()
// double check for reasonable bounds on the
// current value
//
pCF=NULL;
if ( this->pValue.valid () ) {
if (this->pValue->dimension()==1u) {
const gddBounds *pB = this->pValue->getBounds();
if (pB[0u].size()==this->info.getElementCount()) {
pCF = *this->pValue;
}
}
const aitFloat64 *pCF = NULL, *pCFE = NULL;
if (this->pValue.valid () &&
this->pValue->dimension() == 1u) {
const gddBounds *pB = this->pValue->getBounds();
pCF = *this->pValue;
pCFE = &pCF[pB->size()];
}
pFE = &pF[this->info.getElementCount()];
while (pF<pFE) {
radians = (rand () * 2.0 * myPI)/RAND_MAX;
if (pCF) {
aitFloat64 * pFE = &pF[newSize];
while (pF < pFE) {
double radians = (rand () * 2.0 * myPI)/RAND_MAX;
double newValue;
if (pCF && pCF < pCFE) {
newValue = *pCF++;
}
else {
newValue = 0.0f;
}
newValue += (float) (sin (radians) / 10.0);
limit = (float) this->info.getHopr();
newValue += (sin (radians) / 10.0);
double limit = this->info.getHopr();
newValue = tsMin (newValue, limit);
limit = (float) this->info.getLopr();
limit = this->info.getLopr();
newValue = tsMax (newValue, limit);
*(pF++) = newValue;
*pF++ = newValue;
}
aitTimeStamp gddts = this->currentTime;
pDD->setTimeStamp ( & gddts );
status = this->update ( *pDD );
caStatus status = this->update ( *pDD );
this->info.setElementCount(newSize);
if ( status != S_casApp_success ) {
errMessage (status, "vector scan update failed\n");
}
@@ -166,7 +162,7 @@ void exVectorPV::scan()
//
caStatus exVectorPV::updateValue ( const gdd & value )
{
aitUint32 newSize = 0;
//
// Check bounds of incoming request
// (and see if we are replacing all elements -
@@ -183,7 +179,9 @@ caStatus exVectorPV::updateValue ( const gdd & value )
if ( pb[0u].first() != 0u ) {
return S_casApp_outOfBounds;
}
else if ( pb[0u].size() > this->info.getElementCount() ) {
newSize = pb[0u].size();
if ( newSize > this->info.getCapacity() ) {
return S_casApp_outOfBounds;
}
}
@@ -193,14 +191,14 @@ caStatus exVectorPV::updateValue ( const gdd & value )
//
return S_casApp_outOfBounds;
}
//
// Create a new array data descriptor
// (so that old values that may be referenced on the
// event queue are not replaced)
//
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount() ) );
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
1u, newSize ) );
if ( ! pNewValue.valid() ) {
return S_casApp_noMemory;
}
@@ -211,21 +209,20 @@ caStatus exVectorPV::updateValue ( const gdd & value )
//
gddStatus gdds = pNewValue->unreference( );
assert ( ! gdds );
//
// allocate array buffer
//
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
aitFloat64 * pF = new aitFloat64 [newSize];
if (!pF) {
return S_casApp_noMemory;
}
//
// Install (and initialize) array buffer
// if no old values exist
//
unsigned count = this->info.getElementCount();
for ( unsigned i = 0u; i < count; i++ ) {
for ( unsigned i = 0u; i < newSize; i++ ) {
pF[i] = 0.0f;
}
@@ -240,7 +237,7 @@ caStatus exVectorPV::updateValue ( const gdd & value )
// (do this before we increment pF)
//
pNewValue->putRef ( pF, pDest );
//
// copy in the values that they are writing
//
@@ -248,9 +245,10 @@ caStatus exVectorPV::updateValue ( const gdd & value )
if ( gdds ) {
return S_cas_noConvert;
}
this->pValue = pNewValue;
this->info.setElementCount(newSize);
return S_casApp_success;
}
@@ -261,6 +259,6 @@ caStatus exVectorPV::updateValue ( const gdd & value )
//
void exVecDestructor::run ( void *pUntyped )
{
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
aitFloat64 * pf = reinterpret_cast < aitFloat64 * > ( pUntyped );
delete [] pf;
}