cas: Add real implementation for variable length arrays (Bruce Hill, Matej Sekoranja)

This commit is contained in:
Ralph Lange
2016-10-12 13:41:55 +02:00
parent f73d48bb6a
commit 9ac237b3de

View File

@@ -411,17 +411,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;
}
@@ -454,7 +445,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(),
@@ -541,11 +532,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 ) {
@@ -561,21 +556,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 );
}
@@ -595,7 +590,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 );
}
@@ -666,11 +661,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 ) {
@@ -685,23 +684,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 );
}
@@ -859,11 +858,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 ) {
@@ -881,7 +884,7 @@ 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, pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
@@ -902,7 +905,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 );
}
}
@@ -925,14 +928,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 (
@@ -942,7 +945,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 );
}
@@ -1950,7 +1953,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,