diff --git a/src/ca/comBuf.h b/src/ca/comBuf.h index 70a45ed00..b74da3925 100644 --- a/src/ca/comBuf.h +++ b/src/ca/comBuf.h @@ -183,93 +183,93 @@ inline unsigned comBuf::fillFromWire ( wireRecvAdapter & wire ) inline bool comBuf::push ( const epicsInt8 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index ] = static_cast < epicsUInt8 > ( value ); + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index ] = static_cast < epicsUInt8 > ( value ); - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsUInt8 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index ] = value; + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index ] = value; - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsInt16 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index + 0u ] = + static_cast < epicsUInt8 > ( value >> 8u ); + this->buf[ index + 1u ] = + static_cast < epicsUInt8 > ( value >> 0u ); + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index + 0u ] = - static_cast < epicsUInt8 > ( value >> 8u ); - this->buf[ index + 1u ] = - static_cast < epicsUInt8 > ( value >> 0u ); - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsUInt16 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index + 0u ] = + static_cast < epicsUInt8 > ( value >> 8u ); + this->buf[ index + 1u ] = + static_cast < epicsUInt8 > ( value >> 0u ); + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index + 0u ] = - static_cast < epicsUInt8 > ( value >> 8u ); - this->buf[ index + 1u ] = - static_cast < epicsUInt8 > ( value >> 0u ); - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsInt32 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index + 0u ] = + static_cast < epicsUInt8 > ( value >> 24u ); + this->buf[ index + 1u ] = + static_cast < epicsUInt8 > ( value >> 16u ); + this->buf[ index + 2u ] = + static_cast < epicsUInt8 > ( value >> 8u ); + this->buf[ index + 3u ] = + static_cast < epicsUInt8 > ( value >> 0u ); + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index + 0u ] = - static_cast < epicsUInt8 > ( value >> 24u ); - this->buf[ index + 1u ] = - static_cast < epicsUInt8 > ( value >> 16u ); - this->buf[ index + 2u ] = - static_cast < epicsUInt8 > ( value >> 8u ); - this->buf[ index + 3u ] = - static_cast < epicsUInt8 > ( value >> 0u ); - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsUInt32 value ) { unsigned index = this->nextWriteIndex; - unsigned available = sizeof ( this->buf ) - index; - if ( sizeof ( value ) > available ) { - return false; + unsigned nextIndex = index + sizeof ( value ); + if ( nextIndex <= sizeof ( this->buf ) ) { + this->buf[ index + 0u ] = + static_cast < epicsUInt8 > ( value >> 24u ); + this->buf[ index + 1u ] = + static_cast < epicsUInt8 > ( value >> 16u ); + this->buf[ index + 2u ] = + static_cast < epicsUInt8 > ( value >> 8u ); + this->buf[ index + 3u ] = + static_cast < epicsUInt8 > ( value >> 0u ); + this->nextWriteIndex = nextIndex; + return true; } - this->buf[ index + 0u ] = - static_cast < epicsUInt8 > ( value >> 24u ); - this->buf[ index + 1u ] = - static_cast < epicsUInt8 > ( value >> 16u ); - this->buf[ index + 2u ] = - static_cast < epicsUInt8 > ( value >> 8u ); - this->buf[ index + 3u ] = - static_cast < epicsUInt8 > ( value >> 0u ); - this->nextWriteIndex = index + sizeof ( value ); - return true; + return false; } inline bool comBuf::push ( const epicsFloat32 & value ) diff --git a/src/ca/comQueRecv.cpp b/src/ca/comQueRecv.cpp index 944991b30..5aaa198d1 100644 --- a/src/ca/comQueRecv.cpp +++ b/src/ca/comQueRecv.cpp @@ -198,8 +198,6 @@ epicsUInt16 comQueRecv::popUInt16 () comBuf::throwInsufficentBytesException (); } // try first for all in one buffer efficent version - // (double check here avoids slow C++ exception) - // (hopefully optimizer removes inside check) epicsUInt16 tmp; comBuf::popStatus status = pComBuf->pop ( tmp ); if ( status.success ) { @@ -219,8 +217,6 @@ epicsUInt32 comQueRecv::popUInt32 () comBuf::throwInsufficentBytesException (); } // try first for all in one buffer efficent version - // (double check here avoids slow C++ exception) - // (hopefully optimizer removes inside check) epicsUInt32 tmp; comBuf::popStatus status = pComBuf->pop ( tmp ); if ( status.success ) { @@ -232,3 +228,43 @@ epicsUInt32 comQueRecv::popUInt32 () } return this->multiBufferPopUInt32 (); } + +bool comQueRecv::popOldMsgHeader ( caHdrLargeArray & msg ) +{ + // try first for all in one buffer efficent version + comBuf * pComBuf = this->bufs.first (); + if ( ! pComBuf ) { + return false; + } + unsigned avail = pComBuf->occupiedBytes (); + if ( avail >= sizeof ( caHdr ) ) { + pComBuf->pop ( msg.m_cmmd ); + ca_uint16_t smallPostsize; + pComBuf->pop ( smallPostsize ); + msg.m_postsize = smallPostsize; + pComBuf->pop ( msg.m_dataType ); + ca_uint16_t smallCount; + pComBuf->pop ( smallCount ); + msg.m_count = smallCount; + pComBuf->pop ( msg.m_cid ); + pComBuf->pop ( msg.m_available ); + this->nBytesPending -= sizeof ( caHdr ); + if ( avail == sizeof ( caHdr ) ) { + this->removeAndDestroyBuf ( *pComBuf ); + } + return true; + } + else if ( this->occupiedBytes () >= sizeof ( caHdr ) ) { + msg.m_cmmd = this->popUInt16 (); + msg.m_postsize = this->popUInt16 (); + msg.m_dataType = this->popUInt16 (); + msg.m_count = this->popUInt16 (); + msg.m_cid = this->popUInt32 (); + msg.m_available = this->popUInt32 (); + return true; + } + else { + return false; + } +} + diff --git a/src/ca/comQueRecv.h b/src/ca/comQueRecv.h index b00e52c4e..0b3ad08a3 100644 --- a/src/ca/comQueRecv.h +++ b/src/ca/comQueRecv.h @@ -38,6 +38,7 @@ public: unsigned removeBytes ( unsigned nBytes ); void pushLastComBufReceived ( comBuf & ); void clear (); + bool popOldMsgHeader ( struct caHdrLargeArray & ); epicsInt8 popInt8 (); epicsUInt8 popUInt8 (); epicsInt16 popInt16 (); diff --git a/src/ca/comQueSend.cpp b/src/ca/comQueSend.cpp index cb081c662..d1bdf363f 100644 --- a/src/ca/comQueSend.cpp +++ b/src/ca/comQueSend.cpp @@ -120,6 +120,78 @@ void comQueSend::clearUncommitted () } } +void comQueSend::copy_dbr_string ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +void comQueSend::copy_dbr_short ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +void comQueSend::copy_dbr_float ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +void comQueSend::copy_dbr_char ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +void comQueSend::copy_dbr_long ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +void comQueSend::copy_dbr_double ( const void * pValue ) +{ + this->push ( * static_cast ( pValue ) ); +} + +const comQueSend::copyScalarFunc_t comQueSend::dbrCopyScalar [39] = { + &comQueSend::copy_dbr_string, + &comQueSend::copy_dbr_short, + &comQueSend::copy_dbr_float, + &comQueSend::copy_dbr_short, // DBR_ENUM + &comQueSend::copy_dbr_char, + &comQueSend::copy_dbr_long, + &comQueSend::copy_dbr_double, + 0, // DBR_STS_SHORT + 0, // DBR_STS_FLOAT + 0, // DBR_STS_ENUM + 0, // DBR_STS_CHAR + 0, // DBR_STS_LONG + 0, // DBR_STS_DOUBLE + 0, // DBR_TIME_STRING + 0, // DBR_TIME_INT + 0, // DBR_TIME_SHORT + 0, // DBR_TIME_FLOAT + 0, // DBR_TIME_ENUM + 0, // DBR_TIME_CHAR + 0, // DBR_TIME_LONG + 0, // DBR_TIME_DOUBLE + 0, // DBR_GR_STRING + 0, // DBR_GR_SHORT + 0, // DBR_GR_FLOAT + 0, // DBR_GR_ENUM + 0, // DBR_GR_CHAR + 0, // DBR_GR_LONG + 0, // DBR_GR_DOUBLE + 0, // DBR_CTRL_STRING + 0, // DBR_CTRL_SHORT + 0, // DBR_CTRL_FLOAT + 0, // DBR_CTRL_ENUM + 0, // DBR_CTRL_CHAR + 0, // DBR_CTRL_LONG + 0, // DBR_CTRL_DOUBLE + &comQueSend::copy_dbr_short, // DBR_PUT_ACKT + &comQueSend::copy_dbr_short, // DBR_PUT_ACKS + 0, // DBR_STSACK_STRING + 0 // DBR_CLASS_NAME +}; + void comQueSend::copy_dbr_string ( const void *pValue, unsigned nElem ) { this->push ( static_cast ( pValue ), nElem ); @@ -150,7 +222,7 @@ void comQueSend::copy_dbr_double ( const void *pValue, unsigned nElem ) this->push ( static_cast ( pValue ), nElem ); } -const comQueSend::copyFunc_t comQueSend::dbrCopyVector [39] = { +const comQueSend::copyVectorFunc_t comQueSend::dbrCopyVector [39] = { &comQueSend::copy_dbr_string, &comQueSend::copy_dbr_short, &comQueSend::copy_dbr_float, @@ -218,23 +290,34 @@ void comQueSend::insertRequestHeader ( ca_uint32_t requestDependent, bool v49Ok ) { this->beginMsg (); + if ( payloadSize < 0xffff && nElem < 0xffff ) { - this->pushUInt16 ( request ); - this->pushUInt16 ( static_cast < ca_uint16_t > ( payloadSize ) ); - this->pushUInt16 ( dataType ); - this->pushUInt16 ( static_cast < ca_uint16_t > ( nElem ) ); - this->pushUInt32 ( cid ); - this->pushUInt32 ( requestDependent ); + comBuf * pComBuf = this->bufs.last (); + if ( !pComBuf || pComBuf->unoccupiedBytes() < 16u ) { + pComBuf = newComBuf (); + this->pushComBuf ( *pComBuf ); + } + pComBuf->push ( request ); + pComBuf->push ( static_cast < ca_uint16_t > ( payloadSize ) ); + pComBuf->push ( dataType ); + pComBuf->push ( static_cast < ca_uint16_t > ( nElem ) ); + pComBuf->push ( cid ); + pComBuf->push ( requestDependent ); } else if ( v49Ok ) { - this->pushUInt16 ( request ); - this->pushUInt16 ( 0xffff ); - this->pushUInt16 ( dataType ); - this->pushUInt16 ( 0u ); - this->pushUInt32 ( cid ); - this->pushUInt32 ( requestDependent ); - this->pushUInt32 ( payloadSize ); - this->pushUInt32 ( nElem ); + comBuf * pComBuf = this->bufs.last (); + if ( !pComBuf || pComBuf->unoccupiedBytes() < 24u ) { + pComBuf = newComBuf (); + this->pushComBuf ( *pComBuf ); + } + pComBuf->push ( request ); + pComBuf->push ( 0xffff ); + pComBuf->push ( dataType ); + pComBuf->push ( 0u ); + pComBuf->push ( cid ); + pComBuf->push ( requestDependent ); + pComBuf->push ( payloadSize ); + pComBuf->push ( nElem ); } else { throw cacChannel::outOfBounds (); @@ -246,7 +329,7 @@ void comQueSend::insertRequestWithPayLoad ( ca_uint32_t cid, ca_uint32_t requestDependent, const void * pPayload, bool v49Ok ) { - if ( ! this->dbr_type_ok ( dataType ) ) { + if ( dataType >= comQueSendCopyDispatchSize ) { throw cacChannel::badType(); } ca_uint32_t size; @@ -281,7 +364,16 @@ void comQueSend::insertRequestWithPayLoad ( if ( stringOptim ) { this->pushString ( static_cast < const char * > ( pPayload ), size ); } + else if ( nElem == 1u ) { + if ( ! this->dbrCopyScalar [dataType] ) { + throw cacChannel::badType(); + } + ( this->*dbrCopyScalar [dataType] ) ( pPayload ); + } else { + if ( ! this->dbrCopyVector [dataType] ) { + throw cacChannel::badType(); + } ( this->*dbrCopyVector [dataType] ) ( pPayload, nElem ); } // set pad bytes to nill diff --git a/src/ca/comQueSend.h b/src/ca/comQueSend.h index a92265714..5d20170b9 100644 --- a/src/ca/comQueSend.h +++ b/src/ca/comQueSend.h @@ -49,7 +49,6 @@ public: unsigned occupiedBytes () const; bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const; bool flushBlockThreshold ( unsigned nBytesThisMsg ) const; - bool dbr_type_ok ( unsigned type ); void pushUInt16 ( const ca_uint16_t value ); void pushUInt32 ( const ca_uint32_t value ); void pushFloat32 ( const ca_float32_t value ); @@ -69,16 +68,26 @@ private: tsDLIter < comBuf > pFirstUncommited; wireSendAdapter & wire; unsigned nBytesPending; - typedef void ( comQueSend::*copyFunc_t ) ( - const void *pValue, unsigned nElem ); - static const copyFunc_t dbrCopyVector [comQueSendCopyDispatchSize]; + typedef void ( comQueSend::*copyScalarFunc_t ) ( const void * pValue ); + static const copyScalarFunc_t dbrCopyScalar [comQueSendCopyDispatchSize]; + void copy_dbr_string ( const void * pValue ); + void copy_dbr_short ( const void * pValue ); + void copy_dbr_float ( const void * pValue ); + void copy_dbr_char ( const void * pValue ); + void copy_dbr_long ( const void * pValue ); + void copy_dbr_double ( const void * pValue ); + + typedef void ( comQueSend::*copyVectorFunc_t ) ( + const void *pValue, unsigned nElem ); + static const copyVectorFunc_t dbrCopyVector [comQueSendCopyDispatchSize]; void copy_dbr_string ( const void *pValue, unsigned nElem ); void copy_dbr_short ( const void *pValue, unsigned nElem ); void copy_dbr_float ( const void *pValue, unsigned nElem ); void copy_dbr_char ( const void *pValue, unsigned nElem ); void copy_dbr_long ( const void *pValue, unsigned nElem ); void copy_dbr_double ( const void *pValue, unsigned nElem ); + void pushComBuf ( comBuf & ); comBuf * newComBuf (); void clearUncommitted (); @@ -128,17 +137,6 @@ private: extern const char cacNillBytes[]; -inline bool comQueSend::dbr_type_ok ( unsigned type ) -{ - if ( type >= comQueSendCopyDispatchSize ) { - return false; - } - if ( ! this->dbrCopyVector [type] ) { - return false; - } - return true; -} - inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) { this->push ( value ); diff --git a/src/ca/tcpiiu.cpp b/src/ca/tcpiiu.cpp index bacd4665d..65638874d 100644 --- a/src/ca/tcpiiu.cpp +++ b/src/ca/tcpiiu.cpp @@ -751,21 +751,17 @@ bool tcpiiu::processIncoming ( if ( ! this->msgHeaderAvailable ) { if ( ! this->oldMsgHeaderAvailable ) { - if ( nBytes < sizeof ( caHdr ) ) { + this->oldMsgHeaderAvailable = + this->recvQue.popOldMsgHeader ( this->curMsg ); + if ( ! this->oldMsgHeaderAvailable ) { this->flushIfRecvProcessRequested (); return true; - } - this->curMsg.m_cmmd = this->recvQue.popUInt16 (); - this->curMsg.m_postsize = this->recvQue.popUInt16 (); - this->curMsg.m_dataType = this->recvQue.popUInt16 (); - this->curMsg.m_count = this->recvQue.popUInt16 (); - this->curMsg.m_cid = this->recvQue.popUInt32 (); - this->curMsg.m_available = this->recvQue.popUInt32 (); - this->oldMsgHeaderAvailable = true; + } } if ( this->curMsg.m_postsize == 0xffff ) { static const unsigned annexSize = - sizeof ( this->curMsg.m_postsize ) + sizeof ( this->curMsg.m_count ); + sizeof ( this->curMsg.m_postsize ) + + sizeof ( this->curMsg.m_count ); if ( this->recvQue.occupiedBytes () < annexSize ) { this->flushIfRecvProcessRequested (); return true;