diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 52ef97063..14258f352 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,15 @@ +

Add dynamic (variable length) array support to PCAS

+ +

Dynamic array sizing support was added to the IOC server (RSRV) in the +Base-3.14.12 release, but has not until now been supported in the Portable +Channel Access Server (PCAS). Channel Access server applications using the +PCAS will have to be modified slightly to provide full support for variable +length arrays, but unmodified applications will continue to build and work as +before against this release.

+

Additional epicsTime conversion

The EPICS timestamp library (epicsTime) inside libCom's OSI layer has diff --git a/src/cas/generic/caHdrLargeArray.h b/src/cas/generic/caHdrLargeArray.h index 89b0d6d4b..7bda002e9 100644 --- a/src/cas/generic/caHdrLargeArray.h +++ b/src/cas/generic/caHdrLargeArray.h @@ -30,7 +30,7 @@ # include "shareLib.h" #endif -static const unsigned char CA_MINOR_PROTOCOL_REVISION = 12; +static const unsigned char CA_MINOR_PROTOCOL_REVISION = 13; typedef ca_uint32_t caResId; diff --git a/src/cas/generic/casCtx.h b/src/cas/generic/casCtx.h index 706376e77..eab644685 100644 --- a/src/cas/generic/casCtx.h +++ b/src/cas/generic/casCtx.h @@ -18,6 +18,8 @@ #include "caHdrLargeArray.h" +class casStrmClient; + class casCtx { public: casCtx(); @@ -41,6 +43,7 @@ private: casChannelI * pChannel; casPVI * pPV; unsigned nAsyncIO; // checks for improper use of async io + friend class casStrmClient; }; inline const caHdrLargeArray * casCtx::getMsg() const diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index 5bcefb682..468aa17a5 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -390,14 +390,12 @@ caStatus casStrmClient::echoAction ( epicsGuard < casClientMutex > & ) // // casStrmClient::verifyRequest() // -caStatus casStrmClient::verifyRequest ( casChannelI * & pChan ) +caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn) { - const caHdrLargeArray * mp = this->ctx.getMsg(); - // // channel exists for this resource id ? // - chronIntId tmpId ( mp->m_cid ); + chronIntId tmpId ( ctx.msg.m_cid ); pChan = this->chanTable.lookup ( tmpId ); if ( ! pChan ) { return ECA_BADCHID; @@ -406,14 +404,24 @@ caStatus casStrmClient::verifyRequest ( casChannelI * & pChan ) // // data type out of range ? // - if ( mp->m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) { + if ( ctx.msg.m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) { return ECA_BADTYPE; } // // element count out of range ? // - if ( mp->m_count > pChan->getPVI().nativeCount() || mp->m_count == 0u ) { + 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 ) { return ECA_BADCOUNT; } @@ -446,7 +454,7 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard ) casChannelI * pChan; { - caStatus status = this->verifyRequest ( pChan ); + caStatus status = this->verifyRequest ( pChan, true ); if ( status != ECA_NORMAL ) { if ( pChan ) { return this->sendErr ( guard, mp, pChan->getCID(), @@ -587,7 +595,7 @@ caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard casChannelI * pChan; { - caStatus status = this->verifyRequest ( pChan ); + caStatus status = this->verifyRequest ( pChan, true ); if ( status != ECA_NORMAL ) { return this->readNotifyFailureResponse ( guard, * mp, status ); } @@ -1942,7 +1950,7 @@ caStatus casStrmClient::eventAddAction ( casChannelI *pciu; { - caStatus status = casStrmClient::verifyRequest ( pciu ); + caStatus status = casStrmClient::verifyRequest ( pciu, true ); if ( status != ECA_NORMAL ) { if ( pciu ) { return this->sendErr ( guard, mp, diff --git a/src/cas/generic/casStrmClient.h b/src/cas/generic/casStrmClient.h index 3f6c0a51b..0fdd36bb4 100644 --- a/src/cas/generic/casStrmClient.h +++ b/src/cas/generic/casStrmClient.h @@ -69,7 +69,7 @@ private: bool responseIsPending; caStatus createChannel ( const char * pName ); - caStatus verifyRequest ( casChannelI * & pChan ); + caStatus verifyRequest ( casChannelI * & pChan, bool allowdyn = false ); typedef caStatus ( casStrmClient :: * pCASMsgHandler ) ( epicsGuard < casClientMutex > & ); static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];