Client side support for automatic resizing arrays.
In this commit the channel access client is modified to allow a zero size request in a caget or camonitor call. This is passed through to the corresponding CA_PROTO_READ_NOTIFY or CA_PROTO_EVENT__ADD message, but only if the minor version of the protocol is >=13. This commit also adds a new protocol test, CA_V413(), which detects a server which claims to understand the new zero length request. Finally, this commit prepares for a subtle change in the CA protocol. A request for a zero length subscription or data request, which will only be made for protocol version 4.13 and above, is interpreted as a request for autosized data, where the intrinsic dynamic length of the requested waveform should be returned. With the synchronous ca_array_get() call there is no mechanism available to pass back the size of the retrieved data if it is different from the requested count, so the simplest thing is to ensure we don't request autosizing data through this api.
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
|
||||
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
|
||||
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
|
||||
# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
|
||||
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
|
||||
# define CA_V41(MINOR) ( 1u )
|
||||
# define CA_V42(MINOR) ( 1u )
|
||||
@@ -54,6 +55,7 @@
|
||||
# define CA_V410(MINOR) ( 1u )
|
||||
# define CA_V411(MINOR) ( 1u )
|
||||
# define CA_V412(MINOR) ( 1u )
|
||||
# define CA_V413(MINOR) ( 1u )
|
||||
#else
|
||||
# define CA_V41(MINOR) ( 0u )
|
||||
# define CA_V42(MINOR) ( 0u )
|
||||
@@ -67,6 +69,7 @@
|
||||
# define CA_V410(MINOR) ( 0u )
|
||||
# define CA_V411(MINOR) ( 0u )
|
||||
# define CA_V412(MINOR) ( 0u )
|
||||
# define CA_V413(MINOR) ( 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -291,9 +291,6 @@ cacChannel::ioStatus nciu::read (
|
||||
if ( countIn > this->count ) {
|
||||
throw cacChannel::outOfBounds ();
|
||||
}
|
||||
if ( countIn == 0 ) {
|
||||
countIn = this->count;
|
||||
}
|
||||
|
||||
//
|
||||
// fail out if their arguments are invalid
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#define CA_MINOR_PROTOCOL_REVISION 12
|
||||
#define CA_MINOR_PROTOCOL_REVISION 13
|
||||
#include "caProto.h"
|
||||
|
||||
#include "cacIO.h"
|
||||
@@ -205,6 +205,7 @@ public:
|
||||
void disconnectAllIO (
|
||||
epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & );
|
||||
bool connected ( epicsGuard < epicsMutex > & ) const;
|
||||
unsigned getcount() const { return count; }
|
||||
|
||||
private:
|
||||
tsDLList < class baseNMIU > eventq;
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
arrayElementCount getCount (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
epicsGuard < epicsMutex > &, bool allow_zero ) const;
|
||||
unsigned getType (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
unsigned getMask (
|
||||
@@ -242,11 +242,11 @@ inline netSubscription * netSubscription::factory (
|
||||
}
|
||||
|
||||
inline arrayElementCount netSubscription::getCount (
|
||||
epicsGuard < epicsMutex > & guard ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361
|
||||
{
|
||||
//guard.assertIdenticalMutex ( this->mutex );
|
||||
arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );
|
||||
if ( this->count == 0u || this->count > nativeCount ) {
|
||||
if ( (this->count == 0u && !allow_zero) || this->count > nativeCount ) {
|
||||
return nativeCount;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -280,6 +280,9 @@ int epicsShareAPI ca_array_get ( chtype type,
|
||||
if ( type < 0 ) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
if ( count == 0 )
|
||||
return ECA_BADCOUNT;
|
||||
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
|
||||
@@ -1464,6 +1464,8 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
if ( nElem > maxElem ) {
|
||||
throw cacChannel::msgBodyCacheTooSmall ();
|
||||
}
|
||||
if (nElem == 0 && !CA_V413(this->minorProtocolVersion))
|
||||
nElem = chan.getcount();
|
||||
comQueSendMsgMinder minder ( this->sendQue, guard );
|
||||
this->sendQue.insertRequestHeader (
|
||||
CA_PROTO_READ_NOTIFY, 0u,
|
||||
@@ -1559,7 +1561,8 @@ void tcpiiu::subscriptionRequest (
|
||||
if ( mask > 0xffff ) {
|
||||
throw cacChannel::badEventSelection ();
|
||||
}
|
||||
arrayElementCount nElem = subscr.getCount ( guard );
|
||||
arrayElementCount nElem = subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) );
|
||||
arrayElementCount maxBytes;
|
||||
if ( CA_V49 ( this->minorProtocolVersion ) ) {
|
||||
maxBytes = this->cacRef.largeBufferSizeTCP ();
|
||||
@@ -1605,7 +1608,8 @@ void tcpiiu::subscriptionUpdateRequest (
|
||||
if ( this->state != iiucs_connected ) {
|
||||
return;
|
||||
}
|
||||
arrayElementCount nElem = subscr.getCount ( guard );
|
||||
arrayElementCount nElem = subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) );
|
||||
arrayElementCount maxBytes;
|
||||
if ( CA_V49 ( this->minorProtocolVersion ) ) {
|
||||
maxBytes = this->cacRef.largeBufferSizeTCP ();
|
||||
@@ -1643,7 +1647,8 @@ void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard, // X
|
||||
this->sendQue.insertRequestHeader (
|
||||
CA_PROTO_EVENT_CANCEL, 0u,
|
||||
static_cast < ca_uint16_t > ( subscr.getType ( guard ) ),
|
||||
static_cast < ca_uint16_t > ( subscr.getCount ( guard ) ),
|
||||
static_cast < ca_uint16_t > ( subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) ) ),
|
||||
chan.getSID(guard), subscr.getId(),
|
||||
CA_V49 ( this->minorProtocolVersion ) );
|
||||
minder.commit ();
|
||||
|
||||
Reference in New Issue
Block a user